Add analyzers and code-fixes to help adoption of source-generated COM (#87223)
authorJeremy Koritzinsky <jekoritz@microsoft.com>
Fri, 9 Jun 2023 03:36:25 +0000 (20:36 -0700)
committerGitHub <noreply@github.com>
Fri, 9 Jun 2023 03:36:25 +0000 (20:36 -0700)
* Add first pass of the "convert to generated COM interface" analyzer and add tests for the various other analyzers we are going to introduce.

* Get all analyzer-specific components of the "convert" tests passing.

* Implement all interface-attribute-level changes in the code fixer.

* Add bool marshalling insertion logic to the fixer.

* Add support for removing shadowing members from interfaces.

* Rename fixer

* ActiveIssue the new tests

* Implement basic AddGeneratedComClass analyzer/fixer

* Add ComHosting + GeneratedComInterface analyzer implementation.

* Implement the "runtime COM APIs with source-generated COM types" analyzer.

* Factor out a base class from the ConvertToLibraryImportFixer so we can share it with the ComInterfaceGenerator-family of fixers.

* Move more of the ConvertToLibraryImportFixer to use SyntaxGenerator APIs instead of dropping to C#-specific syntax APIs (improves consistency throughout our code fixes)

* Move support for specifying explicit boolean marshalling rules up to the base class.

* Move the code fixes in ComInterfaceGenerator over to using the ConvertToSourceGeneratedInteropFixer base type.

* Remove use of multicasted delegates and use a more traditional "array of delegates" model.

* Do some refactoring to move more into the new fixer base class.

* Remove custom CodeAction-derived types now that we have a record type to represent fixes from the subclasses.

* Make sure we make types and containing types partial

* Fix negative test.

* Add tests for transitive interface inheritance and add iids.

* Change bool parsing for internal parsing and add warning annotation text. Update diagnostics list md.

42 files changed:
docs/project/list-of-diagnostics.md
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/AddGeneratedComClassAnalyzer.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/AddGeneratedComClassFixer.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/AnalyzerDiagnostics.cs
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/ComHostingDoesNotSupportGeneratedComInterfaceAnalyzer.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/ConvertComImportToGeneratedComInterfaceAnalyzer.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/ConvertComImportToGeneratedComInterfaceFixer.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/GeneratedComInterfaceAttributeAnalyzer.cs
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/RuntimeComApiUsageWithSourceGeneratedComAnalyzer.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/AttributeInfo.cs
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/ComInterfaceGenerator.csproj
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceInfo.cs
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodInfo.cs
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratedComInterfaceAttributeData.cs
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/Common/ConvertToSourceGeneratedInteropFixer.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/gen/Common/FixAllContextExtensions.cs [moved from src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/FixAllContextExtensions.cs with 99% similarity]
src/libraries/System.Runtime.InteropServices/gen/Common/OperationExtensions.cs [moved from src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/OperationExtensions.cs with 96% similarity]
src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportFixer.cs
src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj
src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/AddGeneratedComClassTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComHostingDoesNotSupportGeneratedComInterfaceTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ConvertToGeneratedComInterfaceTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/GeneratedComInterfaceAnalyzerTests.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/RuntimeComApiUsageWithSourceGeneratedComTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/ConvertToLibraryImportFixerTests.cs

index d6783d8..eae2823 100644 (file)
@@ -212,10 +212,10 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL
 |  __`SYSLIB1093`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
 |  __`SYSLIB1094`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
 |  __`SYSLIB1095`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
-|  __`SYSLIB1096`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
-|  __`SYSLIB1097`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
-|  __`SYSLIB1098`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
-|  __`SYSLIB1099`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
+|  __`SYSLIB1096`__ | Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time |
+|  __`SYSLIB1097`__ | This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type. |
+|  __`SYSLIB1098`__ | .NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'. |
+|  __`SYSLIB1099`__ | COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime |
 |  __`SYSLIB1100`__ | Configuration binding generator: type is not supported. |
 |  __`SYSLIB1101`__ | Configuration binding generator: property on type is not supported. |
 |  __`SYSLIB1102`__ | Configuration binding generator: project's language version must be at least C# 11.|
diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/AddGeneratedComClassAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/AddGeneratedComClassAnalyzer.cs
new file mode 100644 (file)
index 0000000..29e817b
--- /dev/null
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Immutable;
+using System.Linq;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.DotnetRuntime.Extensions;
+using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics;
+
+namespace Microsoft.Interop.Analyzers
+{
+    [DiagnosticAnalyzer(LanguageNames.CSharp)]
+    public class AddGeneratedComClassAnalyzer : DiagnosticAnalyzer
+    {
+        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(AddGeneratedComClassAttribute);
+
+        public override void Initialize(AnalysisContext context)
+        {
+            context.EnableConcurrentExecution();
+            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+
+            context.RegisterCompilationStartAction(context =>
+            {
+                var generatedComClassAttributeType = context.Compilation.GetBestTypeByMetadataName(TypeNames.GeneratedComClassAttribute);
+                var generatedComInterfaceAttributeType = context.Compilation.GetBestTypeByMetadataName(TypeNames.GeneratedComInterfaceAttribute);
+
+                if (generatedComClassAttributeType is null || generatedComInterfaceAttributeType is null)
+                {
+                    return;
+                }
+
+                context.RegisterSymbolAction(context =>
+                {
+                    INamedTypeSymbol type = (INamedTypeSymbol)context.Symbol;
+                    if (type.GetAttributes().Any(attr => generatedComClassAttributeType.Equals(attr.AttributeClass, SymbolEqualityComparer.Default)))
+                    {
+                        return;
+                    }
+
+                    // Only direct people to put the GeneratedComClassAttribute on classes.
+                    if (type.TypeKind != TypeKind.Class)
+                    {
+                        return;
+                    }
+
+                    foreach (var iface in type.AllInterfaces)
+                    {
+                        if (iface.GetAttributes().Any(attr => generatedComInterfaceAttributeType.Equals(attr.AttributeClass, SymbolEqualityComparer.Default)))
+                        {
+                            context.ReportDiagnostic(type.CreateDiagnostic(AddGeneratedComClassAttribute, type.Name));
+                            return;
+                        }
+                    }
+                }, SymbolKind.NamedType);
+            });
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/AddGeneratedComClassFixer.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/AddGeneratedComClassFixer.cs
new file mode 100644 (file)
index 0000000..716b18c
--- /dev/null
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Immutable;
+using System.Composition;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.DotnetRuntime.Extensions;
+using Microsoft.CodeAnalysis.Editing;
+using Microsoft.CodeAnalysis.Simplification;
+
+namespace Microsoft.Interop.Analyzers
+{
+    [ExportCodeFixProvider(LanguageNames.CSharp), Shared]
+    public class AddGeneratedComClassFixer : ConvertToSourceGeneratedInteropFixer
+    {
+        public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(AnalyzerDiagnostics.Ids.AddGeneratedComClassAttribute);
+
+        protected override string BaseEquivalenceKey => nameof(AddGeneratedComClassFixer);
+
+        private static Task AddGeneratedComClassAsync(DocumentEditor editor, SyntaxNode node)
+        {
+            editor.ReplaceNode(node, (node, gen) =>
+            {
+                var attribute = gen.Attribute(gen.TypeExpression(editor.SemanticModel.Compilation.GetBestTypeByMetadataName(TypeNames.GeneratedComClassAttribute)).WithAdditionalAnnotations(Simplifier.AddImportsAnnotation));
+                var updatedNode = gen.AddAttributes(node, attribute);
+                var declarationModifiers = gen.GetModifiers(updatedNode);
+                if (!declarationModifiers.IsPartial)
+                {
+                    updatedNode = gen.WithModifiers(updatedNode, declarationModifiers.WithPartial(true));
+                }
+                return updatedNode;
+            });
+
+            MakeNodeParentsPartial(editor, node);
+
+            return Task.CompletedTask;
+        }
+
+        protected override Func<DocumentEditor, CancellationToken, Task> CreateFixForSelectedOptions(SyntaxNode node, ImmutableDictionary<string, Option> selectedOptions)
+        {
+            return (editor, _) => AddGeneratedComClassAsync(editor, node);
+        }
+
+        protected override string GetDiagnosticTitle(ImmutableDictionary<string, Option> selectedOptions)
+        {
+            bool allowUnsafe = selectedOptions.TryGetValue(Option.AllowUnsafe, out var allowUnsafeOption) && allowUnsafeOption is Option.Bool(true);
+
+            return allowUnsafe
+                ? SR.AddGeneratedComClassAttributeTitle
+                : SR.AddGeneratedComClassAddUnsafe;
+        }
+
+        protected override ImmutableDictionary<string, Option> ParseOptionsFromDiagnostic(Diagnostic diagnostic)
+        {
+            return ImmutableDictionary<string, Option>.Empty;
+        }
+    }
+}
index beccfb8..53f778c 100644 (file)
@@ -11,9 +11,19 @@ namespace Microsoft.Interop.Analyzers
         {
             public const string Prefix = "SYSLIB";
             public const string InvalidGeneratedComAttributeUsage = Prefix + "1090";
+            public const string ConvertToGeneratedComInterface = Prefix + "1096";
+            public const string AddGeneratedComClassAttribute = Prefix + "1097";
+            public const string ComHostingDoesNotSupportGeneratedComInterface = Prefix + "1098";
+            public const string RuntimeComApisDoNotSupportSourceGeneratedCom = Prefix + "1099";
         }
 
-        private const string Category = "ComInterfaceGenerator";
+        public static class Metadata
+        {
+            public const string MayRequireAdditionalWork = nameof(MayRequireAdditionalWork);
+            public const string AddStringMarshalling = nameof(AddStringMarshalling);
+        }
+
+        private const string Category = "Interoperability";
 
         private static LocalizableResourceString GetResourceString(string resourceName)
         {
@@ -29,5 +39,45 @@ namespace Microsoft.Interop.Analyzers
                 DiagnosticSeverity.Error,
                 isEnabledByDefault: true,
                 description: GetResourceString(nameof(SR.InterfaceTypeNotSupportedMessage)));
+
+        public static readonly DiagnosticDescriptor ConvertToGeneratedComInterface =
+            new DiagnosticDescriptor(
+                Ids.ConvertToGeneratedComInterface,
+                GetResourceString(nameof(SR.ConvertToGeneratedComInterfaceTitle)),
+                GetResourceString(nameof(SR.ConvertToGeneratedComInterfaceMessage)),
+                Category,
+                DiagnosticSeverity.Info,
+                isEnabledByDefault: true,
+                description: GetResourceString(nameof(SR.ConvertToGeneratedComInterfaceDescription)));
+
+        public static readonly DiagnosticDescriptor AddGeneratedComClassAttribute =
+            new DiagnosticDescriptor(
+                Ids.AddGeneratedComClassAttribute,
+                GetResourceString(nameof(SR.AddGeneratedComClassAttributeTitle)),
+                GetResourceString(nameof(SR.AddGeneratedComClassAttributeMessage)),
+                Category,
+                DiagnosticSeverity.Info,
+                isEnabledByDefault: true,
+                description: GetResourceString(nameof(SR.AddGeneratedComClassAttributeDescription)));
+
+        public static readonly DiagnosticDescriptor ComHostingDoesNotSupportGeneratedComInterface =
+            new DiagnosticDescriptor(
+                Ids.ComHostingDoesNotSupportGeneratedComInterface,
+                GetResourceString(nameof(SR.ComHostingDoesNotSupportGeneratedComInterfaceTitle)),
+                GetResourceString(nameof(SR.ComHostingDoesNotSupportGeneratedComInterfaceMessage)),
+                Category,
+                DiagnosticSeverity.Warning,
+                isEnabledByDefault: true,
+                description: GetResourceString(nameof(SR.ComHostingDoesNotSupportGeneratedComInterfaceDescription)));
+
+        public static readonly DiagnosticDescriptor RuntimeComApisDoNotSupportSourceGeneratedCom =
+            new DiagnosticDescriptor(
+                Ids.RuntimeComApisDoNotSupportSourceGeneratedCom,
+                GetResourceString(nameof(SR.RuntimeComApisDoNotSupportSourceGeneratedComTitle)),
+                GetResourceString(nameof(SR.RuntimeComApisDoNotSupportSourceGeneratedComMessage)),
+                Category,
+                DiagnosticSeverity.Warning,
+                isEnabledByDefault: true,
+                description: GetResourceString(nameof(SR.RuntimeComApisDoNotSupportSourceGeneratedComDescription)));
     }
 }
diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/ComHostingDoesNotSupportGeneratedComInterfaceAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/ComHostingDoesNotSupportGeneratedComInterfaceAnalyzer.cs
new file mode 100644 (file)
index 0000000..4efd732
--- /dev/null
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Immutable;
+using System.Linq;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.DotnetRuntime.Extensions;
+using Microsoft.CodeAnalysis.Operations;
+using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics;
+
+namespace Microsoft.Interop.Analyzers
+{
+    [DiagnosticAnalyzer(LanguageNames.CSharp)]
+    public class ComHostingDoesNotSupportGeneratedComInterfaceAnalyzer : DiagnosticAnalyzer
+    {
+        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(ComHostingDoesNotSupportGeneratedComInterface);
+
+        public override void Initialize(AnalysisContext context)
+        {
+            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+            context.EnableConcurrentExecution();
+            context.RegisterCompilationStartAction(context =>
+            {
+                if (!context.Options.AnalyzerConfigOptionsProvider.GlobalOptions.TryGetValue("build_property.EnableComHosting", out string? enableComHosting)
+                    || !bool.TryParse(enableComHosting, out bool enableComHostingValue)
+                    || !enableComHostingValue)
+                {
+                    return;
+                }
+
+                INamedTypeSymbol? generatedComClassAttribute = context.Compilation.GetBestTypeByMetadataName(TypeNames.GeneratedComClassAttribute);
+                INamedTypeSymbol? generatedComInterfaceAttribute = context.Compilation.GetBestTypeByMetadataName(TypeNames.GeneratedComInterfaceAttribute);
+                INamedTypeSymbol? comVisibleAttribute = context.Compilation.GetBestTypeByMetadataName(TypeNames.System_Runtime_InteropServices_ComVisibleAttribute)!;
+
+                if (generatedComClassAttribute is null || generatedComInterfaceAttribute is null || comVisibleAttribute is null)
+                {
+                    return;
+                }
+
+                context.RegisterOperationAction(context =>
+                {
+                    IAttributeOperation attr = (IAttributeOperation)context.Operation;
+                    if (attr.Operation is not IObjectCreationOperation ctor
+                        || !comVisibleAttribute.Equals(ctor.Type, SymbolEqualityComparer.Default)
+                        || ctor.Arguments[0].Value.ConstantValue.Value is not true)
+                    {
+                        return;
+                    }
+
+                    INamedTypeSymbol containingType = (INamedTypeSymbol)context.ContainingSymbol;
+
+                    if (containingType.GetAttributes().Any(attr => generatedComClassAttribute.Equals(attr.AttributeClass, SymbolEqualityComparer.Default)))
+                    {
+                        context.ReportDiagnostic(context.ContainingSymbol.CreateDiagnostic(ComHostingDoesNotSupportGeneratedComInterface, context.ContainingSymbol.Name));
+                        return;
+                    }
+
+                    foreach (var iface in containingType.AllInterfaces)
+                    {
+                        if (iface.GetAttributes().Any(attr => generatedComInterfaceAttribute.Equals(attr.AttributeClass, SymbolEqualityComparer.Default)))
+                        {
+                            context.ReportDiagnostic(context.ContainingSymbol.CreateDiagnostic(ComHostingDoesNotSupportGeneratedComInterface, context.ContainingSymbol.Name));
+                            return;
+                        }
+                    }
+                }, OperationKind.Attribute);
+            });
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/ConvertComImportToGeneratedComInterfaceAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/ConvertComImportToGeneratedComInterfaceAnalyzer.cs
new file mode 100644 (file)
index 0000000..1449bcc
--- /dev/null
@@ -0,0 +1,233 @@
+// 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.Linq;
+using System.Runtime.InteropServices;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.DotnetRuntime.Extensions;
+using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics;
+
+namespace Microsoft.Interop.Analyzers
+{
+    [DiagnosticAnalyzer(LanguageNames.CSharp)]
+    public class ConvertComImportToGeneratedComInterfaceAnalyzer : DiagnosticAnalyzer
+    {
+        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(ConvertToGeneratedComInterface);
+
+        private static readonly HashSet<string> s_unsupportedTypeNames = new()
+        {
+            "global::System.Runtime.InteropServices.CriticalHandle",
+            "global::System.Runtime.InteropServices.HandleRef",
+            "global::System.Text.StringBuilder"
+        };
+
+        public override void Initialize(AnalysisContext context)
+        {
+            context.EnableConcurrentExecution();
+            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+
+            context.RegisterCompilationStartAction(context =>
+            {
+                INamedTypeSymbol? interfaceTypeAttribute = context.Compilation.GetBestTypeByMetadataName(TypeNames.InterfaceTypeAttribute)!;
+                INamedTypeSymbol? generatedComInterfaceAttribute = context.Compilation.GetBestTypeByMetadataName(TypeNames.GeneratedComInterfaceAttribute);
+
+                if (generatedComInterfaceAttribute is null)
+                {
+                    return;
+                }
+
+                TargetFrameworkSettings targetFramework = context.Options.AnalyzerConfigOptionsProvider.GlobalOptions.GetTargetFrameworkSettings();
+                var env = new StubEnvironment(
+                    context.Compilation,
+                    targetFramework.TargetFramework,
+                    targetFramework.Version,
+                    context.Compilation.SourceModule.GetAttributes().Any(attr => attr.AttributeClass.ToDisplayString() == TypeNames.System_Runtime_CompilerServices_SkipLocalsInitAttribute));
+
+                context.RegisterSymbolAction(context =>
+                {
+                    INamedTypeSymbol type = (INamedTypeSymbol)context.Symbol;
+                    AttributeData? interfaceTypeAttributeData = type.GetAttributes().FirstOrDefault(a => a.AttributeClass.Equals(interfaceTypeAttribute, SymbolEqualityComparer.Default));
+                    if (type is not { TypeKind: TypeKind.Interface, IsComImport: true }
+                        || interfaceTypeAttributeData.ConstructorArguments.Length == 1 && (int)interfaceTypeAttributeData.ConstructorArguments[0].Value != (int)ComInterfaceType.InterfaceIsIUnknown)
+                    {
+                        return;
+                    }
+
+                    bool mayRequireAdditionalWork = false;
+                    bool hasStrings = false;
+                    if (type.DeclaringSyntaxReferences.Length > 1)
+                    {
+                        mayRequireAdditionalWork = true;
+                    }
+
+                    foreach (var method in type.GetMembers().OfType<IMethodSymbol>().Where(m => !m.IsStatic && m.IsAbstract))
+                    {
+                        // Ignore types with methods with unsupported returns
+                        if (method.ReturnsByRef || method.ReturnsByRefReadonly)
+                            return;
+                        // Run a basic conversion check like we do for ConvertToLibraryImportAttributeAnalyzer to determine if there will be warnings after the fix.
+
+                        // Use  the method signature to do some of the work the generator will do after conversion.
+                        // If any diagnostics or failures to marshal are reported, then mark this diagnostic with a property signifying that it may require
+                        // later user work.
+                        AnyDiagnosticsSink diagnostics = new();
+                        AttributeData comImportAttribute = type.GetAttributes().First(attr => attr.AttributeClass.ToDisplayString() == TypeNames.System_Runtime_InteropServices_ComImportAttribute);
+                        SignatureContext targetSignatureContext = SignatureContext.Create(
+                            method,
+                            CreateComImportMarshallingInfoParser(env, diagnostics, method, comImportAttribute),
+                            env,
+                            typeof(ConvertComImportToGeneratedComInterfaceAnalyzer).Assembly);
+
+                        var managedToUnmanagedFactory = ComInterfaceGeneratorHelpers.CreateGeneratorFactory(env, MarshalDirection.ManagedToUnmanaged);
+                        var unmanagedToManagedFactory = ComInterfaceGeneratorHelpers.CreateGeneratorFactory(env, MarshalDirection.UnmanagedToManaged);
+
+                        mayRequireAdditionalWork = diagnostics.AnyDiagnostics;
+                        bool anyExplicitlyUnsupportedInfo = false;
+
+                        var managedToNativeStubCodeContext = new ManagedToNativeStubCodeContext(env.TargetFramework, env.TargetFrameworkVersion, "return", "nativeReturn");
+                        var nativeToManagedStubCodeContext = new NativeToManagedStubCodeContext(env.TargetFramework, env.TargetFrameworkVersion, "return", "nativeReturn");
+
+                        var forwarder = new Forwarder();
+                        // We don't actually need the bound generators. We just need them to be attempted to be bound to determine if the generator will be able to bind them.
+                        BoundGenerators generators = BoundGenerators.Create(targetSignatureContext.ElementTypeInformation, new CallbackGeneratorFactory((info, context) =>
+                        {
+                            if (s_unsupportedTypeNames.Contains(info.ManagedType.FullTypeName))
+                            {
+                                anyExplicitlyUnsupportedInfo = true;
+                                return forwarder;
+                            }
+                            if (HasUnsupportedMarshalAsInfo(info))
+                            {
+                                anyExplicitlyUnsupportedInfo = true;
+                                return forwarder;
+                            }
+                            if (info.MarshallingAttributeInfo is TrackedMarshallingInfo(TrackedMarshallingInfoAnnotation.ExplicitlyUnsupported, _))
+                            {
+                                anyExplicitlyUnsupportedInfo = true;
+                                return forwarder;
+                            }
+                            if (info.MarshallingAttributeInfo is TrackedMarshallingInfo(TrackedMarshallingInfoAnnotation annotation, var inner))
+                            {
+                                if (annotation == TrackedMarshallingInfoAnnotation.String)
+                                {
+                                    hasStrings = true;
+                                }
+                                info = info with { MarshallingAttributeInfo = inner };
+                            }
+                            // Run both factories and collect any binding failures.
+                            _ = unmanagedToManagedFactory.GeneratorFactory.Create(info, nativeToManagedStubCodeContext);
+                            return managedToUnmanagedFactory.GeneratorFactory.Create(info, managedToNativeStubCodeContext);
+                        }), managedToNativeStubCodeContext, forwarder, out var bindingFailures);
+
+                        mayRequireAdditionalWork |= bindingFailures.Length > 0;
+
+                        if (anyExplicitlyUnsupportedInfo)
+                        {
+                            // If we have any parameters/return value with an explicitly unsupported marshal type or marshalling info,
+                            // don't offer the fix. The amount of work for the user to get to pairity would be too expensive.
+                            return;
+                        }
+                    }
+
+                    ImmutableDictionary<string, string>.Builder properties = ImmutableDictionary.CreateBuilder<string, string>();
+
+                    properties.Add(AnalyzerDiagnostics.Metadata.MayRequireAdditionalWork, mayRequireAdditionalWork.ToString());
+                    properties.Add(AnalyzerDiagnostics.Metadata.AddStringMarshalling, hasStrings.ToString());
+
+                    context.ReportDiagnostic(type.CreateDiagnostic(ConvertToGeneratedComInterface, properties.ToImmutable(), type.Name));
+                }, SymbolKind.NamedType);
+            });
+        }
+
+        private static MarshallingInfoParser CreateComImportMarshallingInfoParser(StubEnvironment env, IGeneratorDiagnostics diagnostics, IMethodSymbol method, AttributeData unparsedAttributeData)
+        {
+            var defaultInfo = new DefaultMarshallingInfo(CharEncoding.Utf16, null);
+
+            var useSiteAttributeParsers = ImmutableArray.Create<IUseSiteAttributeParser>(
+                    new MarshalAsAttributeParser(env.Compilation, diagnostics, defaultInfo),
+                    new MarshalUsingAttributeParser(env.Compilation, diagnostics));
+
+            return new MarshallingInfoParser(
+                diagnostics,
+                new MethodSignatureElementInfoProvider(env.Compilation, diagnostics, method, useSiteAttributeParsers),
+                useSiteAttributeParsers,
+                ImmutableArray.Create<IMarshallingInfoAttributeParser>(
+                    new MarshalAsAttributeParser(env.Compilation, diagnostics, defaultInfo),
+                    new MarshalUsingAttributeParser(env.Compilation, diagnostics),
+                    new NativeMarshallingAttributeParser(env.Compilation, diagnostics),
+                    new ComInterfaceMarshallingInfoProvider(env.Compilation)),
+                ImmutableArray.Create<ITypeBasedMarshallingInfoProvider>(
+                    new SafeHandleMarshallingInfoProvider(env.Compilation, method.ContainingType),
+                    new ExplicitlyUnsupportedMarshallingInfoProvider(), // We don't support arrays, so we don't include the array marshalling info provider. Instead, we include our "explicitly unsupported" provider.
+                    new CharMarshallingInfoProvider(defaultInfo),
+                    new TrackingStringMarshallingInfoProvider(new StringMarshallingInfoProvider(env.Compilation, diagnostics, unparsedAttributeData, defaultInfo)), // We need to mark when we see string types to ensure we offer a code-fix that adds the string marshalling info.
+                    new BooleanMarshallingInfoProvider(),
+                    new BlittableTypeMarshallingInfoProvider(env.Compilation)));
+        }
+
+        private static bool HasUnsupportedMarshalAsInfo(TypePositionInfo info)
+        {
+            if (info.MarshallingAttributeInfo is not MarshalAsInfo(UnmanagedType unmanagedType, _))
+                return false;
+
+            return !Enum.IsDefined(typeof(UnmanagedType), unmanagedType)
+                || unmanagedType == UnmanagedType.CustomMarshaler
+                || unmanagedType == UnmanagedType.Interface
+                || unmanagedType == UnmanagedType.IDispatch
+                || unmanagedType == UnmanagedType.IInspectable
+                || unmanagedType == UnmanagedType.IUnknown
+                || unmanagedType == UnmanagedType.SafeArray;
+        }
+
+        private sealed class AnyDiagnosticsSink : IGeneratorDiagnostics
+        {
+            public bool AnyDiagnostics { get; private set; }
+            public void ReportConfigurationNotSupported(AttributeData attributeData, string configurationName, string? unsupportedValue) => AnyDiagnostics = true;
+            public void ReportInvalidMarshallingAttributeInfo(AttributeData attributeData, string reasonResourceName, params string[] reasonArgs) => AnyDiagnostics = true;
+        }
+
+        private sealed class CallbackGeneratorFactory : IMarshallingGeneratorFactory
+        {
+            private readonly Func<TypePositionInfo, StubCodeContext, IMarshallingGenerator> _func;
+
+            public CallbackGeneratorFactory(Func<TypePositionInfo, StubCodeContext, IMarshallingGenerator> func)
+            {
+                _func = func;
+            }
+
+            public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context) => _func(info, context);
+        }
+
+        private enum TrackedMarshallingInfoAnnotation
+        {
+            ExplicitlyUnsupported,
+            String
+        }
+
+        private sealed record TrackedMarshallingInfo(TrackedMarshallingInfoAnnotation TrackingAnnotation, MarshallingInfo InnerInfo): MarshallingInfo;
+
+        private sealed class TrackingStringMarshallingInfoProvider : ITypeBasedMarshallingInfoProvider
+        {
+            private readonly ITypeBasedMarshallingInfoProvider _stringMarshallingInfoProvider;
+
+            public TrackingStringMarshallingInfoProvider(ITypeBasedMarshallingInfoProvider stringMarshallingInfoProvider)
+            {
+                _stringMarshallingInfoProvider = stringMarshallingInfoProvider;
+            }
+
+            public bool CanProvideMarshallingInfoForType(ITypeSymbol type) => type.SpecialType == SpecialType.System_String;
+            public MarshallingInfo GetMarshallingInfo(ITypeSymbol type, int indirectionDepth, UseSiteAttributeProvider useSiteAttributes, GetMarshallingInfoCallback marshallingInfoCallback)
+                => new TrackedMarshallingInfo(TrackedMarshallingInfoAnnotation.String, _stringMarshallingInfoProvider.GetMarshallingInfo(type, indirectionDepth, useSiteAttributes, marshallingInfoCallback));
+        }
+
+        private sealed class ExplicitlyUnsupportedMarshallingInfoProvider : ITypeBasedMarshallingInfoProvider
+        {
+            public bool CanProvideMarshallingInfoForType(ITypeSymbol type) => type is { TypeKind: TypeKind.Array or TypeKind.Delegate } or { SpecialType: SpecialType.System_Array or SpecialType.System_Object };
+            public MarshallingInfo GetMarshallingInfo(ITypeSymbol type, int indirectionDepth, UseSiteAttributeProvider useSiteAttributes, GetMarshallingInfoCallback marshallingInfoCallback) => new TrackedMarshallingInfo(TrackedMarshallingInfoAnnotation.ExplicitlyUnsupported, NoMarshallingInfo.Instance);
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/ConvertComImportToGeneratedComInterfaceFixer.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/ConvertComImportToGeneratedComInterfaceFixer.cs
new file mode 100644 (file)
index 0000000..081b608
--- /dev/null
@@ -0,0 +1,123 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Immutable;
+using System.Composition;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CodeActions;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.Editing;
+using Microsoft.CodeAnalysis.Simplification;
+
+namespace Microsoft.Interop.Analyzers
+{
+    [ExportCodeFixProvider(LanguageNames.CSharp), Shared]
+    public sealed class ConvertComImportToGeneratedComInterfaceFixer : ConvertToSourceGeneratedInteropFixer
+    {
+        private const string AddStringMarshallingOption = nameof(AddStringMarshallingOption);
+
+        protected override string BaseEquivalenceKey => "ConvertToGeneratedComInterface";
+
+        public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(AnalyzerDiagnostics.Ids.ConvertToGeneratedComInterface);
+
+        protected override string GetDiagnosticTitle(ImmutableDictionary<string, Option> selectedOptions)
+        {
+            return selectedOptions.TryGetValue(Option.AllowUnsafe, out Option allowUnsafeOption) && allowUnsafeOption is Option.Bool(true)
+                ? SR.ConvertToGeneratedComInterfaceAddUnsafe
+                : SR.ConvertToGeneratedComInterfaceTitle;
+        }
+
+        protected override Func<DocumentEditor, CancellationToken, Task> CreateFixForSelectedOptions(SyntaxNode node, ImmutableDictionary<string, Option> selectedOptions)
+        {
+            bool mayRequireAdditionalWork = selectedOptions.TryGetValue(Option.MayRequireAdditionalWork, out Option mayRequireAdditionalWorkOption) && mayRequireAdditionalWorkOption is Option.Bool(true);
+            bool addStringMarshalling = selectedOptions.TryGetValue(AddStringMarshallingOption, out Option addStringMarshallingOption) && addStringMarshallingOption is Option.Bool(true);
+
+            return (editor, ct) => ConvertComImportToGeneratedComInterfaceAsync(editor, node, mayRequireAdditionalWork, addStringMarshalling, ct);
+        }
+
+        protected override ImmutableDictionary<string, Option> ParseOptionsFromDiagnostic(Diagnostic diagnostic)
+        {
+            var optionsBuilder = ImmutableDictionary.CreateBuilder<string, Option>();
+            // Only add the bool options if they are true. This simplifies our equivalence key and makes testing easier.
+            if (diagnostic.Properties.TryGetValue(AnalyzerDiagnostics.Metadata.MayRequireAdditionalWork, out string? mayRequireAdditionalWork) && bool.Parse(mayRequireAdditionalWork))
+            {
+                optionsBuilder.Add(Option.MayRequireAdditionalWork, new Option.Bool(true));
+            }
+            if (diagnostic.Properties.TryGetValue(AnalyzerDiagnostics.Metadata.AddStringMarshalling, out string? addStringMarshalling) && bool.Parse(addStringMarshalling))
+            {
+                optionsBuilder.Add(AddStringMarshallingOption, new Option.Bool(true));
+            }
+            return optionsBuilder.ToImmutable();
+        }
+
+        private static async Task ConvertComImportToGeneratedComInterfaceAsync(DocumentEditor editor, SyntaxNode node, bool mayRequireAdditionalWork, bool addStringMarshalling, CancellationToken ct)
+        {
+            var gen = editor.Generator;
+            var comp = editor.SemanticModel.Compilation;
+            var declaringType = editor.SemanticModel.GetDeclaredSymbol(node, ct);
+
+            var generatedComInterfaceAttribute = gen.Attribute(gen.TypeExpression(comp.GetTypeByMetadataName(TypeNames.GeneratedComInterfaceAttribute)).WithAdditionalAnnotations(Simplifier.AddImportsAnnotation));
+
+            if (addStringMarshalling)
+            {
+                generatedComInterfaceAttribute = gen.AddAttributeArguments(
+                    generatedComInterfaceAttribute,
+                    new[]
+                    {
+                       gen.AttributeArgument("StringMarshalling", gen.MemberAccessExpression(gen.DottedName(TypeNames.StringMarshalling), gen.IdentifierName(nameof(StringMarshalling.Custom)))),
+                       gen.AttributeArgument("StringMarshallingCustomType", gen.TypeOfExpression(gen.TypeExpression(comp.GetTypeByMetadataName(TypeNames.BStrStringMarshaller))))
+                    });
+            }
+
+            if (mayRequireAdditionalWork)
+            {
+                generatedComInterfaceAttribute = generatedComInterfaceAttribute.WithAdditionalAnnotations(
+                    WarningAnnotation.Create(SR.ConvertComInterfaceMayProduceInvalidCode));
+            }
+
+            var comImportAttributeType = comp.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_ComImportAttribute);
+
+            var comImportAttribute = await declaringType.GetAttributes().First(attr => attr.AttributeClass.Equals(comImportAttributeType, SymbolEqualityComparer.Default)).ApplicationSyntaxReference.GetSyntaxAsync(ct).ConfigureAwait(false);
+
+            editor.ReplaceNode(comImportAttribute, generatedComInterfaceAttribute);
+
+            foreach (var member in gen.GetMembers(node))
+            {
+                if (gen.GetDeclarationKind(member) != DeclarationKind.Method)
+                {
+                    continue;
+                }
+
+                var declarationModifiers = gen.GetModifiers(member);
+
+                if (declarationModifiers.IsStatic)
+                {
+                    continue;
+                }
+
+                if (declarationModifiers.IsNew)
+                {
+                    // If this is a shadowing method, then we remove it.
+                    // TODO: Do we want to be smarter here and try to match the number of methods to a base interface, etc.?
+                    editor.RemoveNode(member);
+                    continue;
+                }
+
+                IMethodSymbol method = (IMethodSymbol)editor.SemanticModel.GetDeclaredSymbol(member, ct);
+                var generatedDeclaration = member;
+
+                generatedDeclaration = AddExplicitDefaultBoolMarshalling(gen, method, generatedDeclaration, "VariantBool");
+                editor.ReplaceNode(member, generatedDeclaration);
+            }
+
+            editor.ReplaceNode(node, (node, gen) => gen.WithModifiers(node, gen.GetModifiers(node).WithPartial(true)));
+
+            MakeNodeParentsPartial(editor, node);
+        }
+
+    }
+}
index 9779d1e..f3fecba 100644 (file)
@@ -59,7 +59,7 @@ namespace Microsoft.Interop.Analyzers
             argument = ctorArg0.ToCSharpString();
             switch (ctorArg0.Type.ToDisplayString())
             {
-                case TypeNames.ComInterfaceTypeAttribute:
+                case TypeNames.ComInterfaceType:
                     interfaceType = (ComInterfaceType)ctorArg0.Value;
                     break;
                 case TypeNames.System_Int16:
diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/RuntimeComApiUsageWithSourceGeneratedComAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/RuntimeComApiUsageWithSourceGeneratedComAnalyzer.cs
new file mode 100644 (file)
index 0000000..41b9c65
--- /dev/null
@@ -0,0 +1,176 @@
+// 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.Linq;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.DotnetRuntime.Extensions;
+using Microsoft.CodeAnalysis.Operations;
+using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics;
+
+namespace Microsoft.Interop.Analyzers
+{
+    [DiagnosticAnalyzer(LanguageNames.CSharp)]
+    public class RuntimeComApiUsageWithSourceGeneratedComAnalyzer : DiagnosticAnalyzer
+    {
+        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(RuntimeComApisDoNotSupportSourceGeneratedCom);
+
+        public override void Initialize(AnalysisContext context)
+        {
+            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+            context.EnableConcurrentExecution();
+            context.RegisterCompilationStartAction(context =>
+            {
+                INamedTypeSymbol? marshalType = context.Compilation.GetBestTypeByMetadataName(TypeNames.System_Runtime_InteropServices_Marshal);
+                INamedTypeSymbol? generatedComClassAttribute = context.Compilation.GetBestTypeByMetadataName(TypeNames.GeneratedComClassAttribute);
+                INamedTypeSymbol? generatedComInterfaceAttribute = context.Compilation.GetBestTypeByMetadataName(TypeNames.GeneratedComInterfaceAttribute);
+                INamedTypeSymbol? comObjectType = context.Compilation.GetBestTypeByMetadataName(TypeNames.System_Runtime_InteropServices_Marshalling_ComObject);
+
+                List<Func<ITypeSymbol, bool>> sourceGeneratedComRecognizers = new();
+                if (generatedComClassAttribute is not null)
+                {
+                    sourceGeneratedComRecognizers.Add(type => type.GetAttributes().Any(attr => generatedComClassAttribute.Equals(attr.AttributeClass, SymbolEqualityComparer.Default)));
+                }
+                if (generatedComInterfaceAttribute is not null)
+                {
+                    sourceGeneratedComRecognizers.Add(type => type.GetAttributes().Any(attr => generatedComInterfaceAttribute.Equals(attr.AttributeClass, SymbolEqualityComparer.Default)));
+                }
+                if (comObjectType is not null)
+                {
+                    sourceGeneratedComRecognizers.Add(type => type.Equals(comObjectType, SymbolEqualityComparer.Default));
+                }
+
+                if (marshalType is null || sourceGeneratedComRecognizers.Count == 0)
+                {
+                    return;
+                }
+
+                var methodsOfInterest = new Dictionary<ISymbol, ImmutableArray<Func<IInvocationOperation, (ITypeSymbol, Location)?>>>(SymbolEqualityComparer.Default);
+
+                var firstArgumentTypeLookup = CreateArgumentTypeLookup(0);
+
+                var firstArgumentTypeLookupOnly = ImmutableArray.Create(firstArgumentTypeLookup);
+
+                methodsOfInterest.Add(marshalType.GetMembers("SetComObjectData")[0], firstArgumentTypeLookupOnly);
+                methodsOfInterest.Add(marshalType.GetMembers("GetComObjectData")[0], firstArgumentTypeLookupOnly);
+                methodsOfInterest.Add(marshalType.GetMembers("ReleaseComObject")[0], firstArgumentTypeLookupOnly);
+                methodsOfInterest.Add(marshalType.GetMembers("FinalReleaseComObject")[0], firstArgumentTypeLookupOnly);
+
+                foreach (var createAggregatedObject in marshalType.GetMembers("CreateAggregatedObject"))
+                {
+                    if (createAggregatedObject is IMethodSymbol { IsGenericMethod: true })
+                    {
+                        methodsOfInterest.Add(createAggregatedObject, ImmutableArray.Create(CreateTypeArgumentTypeLookup(0), CreateArgumentTypeLookup(1)));
+                    }
+                    else
+                    {
+                        methodsOfInterest.Add(createAggregatedObject, ImmutableArray.Create(CreateArgumentTypeLookup(1)));
+                    }
+                }
+
+                foreach (var createWrapperOfType in marshalType.GetMembers("CreateWrapperOfType"))
+                {
+                    if (createWrapperOfType is IMethodSymbol { IsGenericMethod: true })
+                    {
+                        methodsOfInterest.Add(createWrapperOfType, ImmutableArray.Create(CreateTypeArgumentTypeLookup(0), CreateTypeArgumentTypeLookup(1), firstArgumentTypeLookup));
+                    }
+                    else
+                    {
+                        methodsOfInterest.Add(createWrapperOfType, ImmutableArray.Create(firstArgumentTypeLookup, CreateTypeOfArgumentTypeLookup(1)));
+                    }
+                }
+
+                methodsOfInterest.Add(marshalType.GetMembers("GetTypedObjectForIUnknown")[0], ImmutableArray.Create(CreateTypeOfArgumentTypeLookup(1)));
+                methodsOfInterest.Add(marshalType.GetMembers("GetIUnknownForObject")[0], firstArgumentTypeLookupOnly);
+                methodsOfInterest.Add(marshalType.GetMembers("GetIDispatchForObject")[0], firstArgumentTypeLookupOnly);
+
+                foreach (var getComInterfaceForObject in marshalType.GetMembers("GetComInterfaceForObject"))
+                {
+                    if (getComInterfaceForObject is IMethodSymbol { IsGenericMethod: true })
+                    {
+                        methodsOfInterest.Add(getComInterfaceForObject, ImmutableArray.Create(CreateTypeArgumentTypeLookup(0), CreateTypeArgumentTypeLookup(1), firstArgumentTypeLookup));
+                    }
+                    else
+                    {
+                        methodsOfInterest.Add(getComInterfaceForObject, ImmutableArray.Create(CreateArgumentTypeLookup(0), CreateTypeOfArgumentTypeLookup(1)));
+                    }
+                }
+
+                context.RegisterOperationAction(context =>
+                {
+                    var operation = (IInvocationOperation)context.Operation;
+
+                    if (methodsOfInterest.TryGetValue(operation.TargetMethod.OriginalDefinition, out ImmutableArray<Func<IInvocationOperation, (ITypeSymbol, Location)?>> discoverers))
+                    {
+                        foreach (Func<IInvocationOperation, (ITypeSymbol, Location)?> discoverer in discoverers)
+                        {
+                            var typeInfo = discoverer(operation);
+                            if (typeInfo is (ITypeSymbol targetType, Location diagnosticLocation))
+                            {
+                                foreach (var recognizer in sourceGeneratedComRecognizers)
+                                {
+                                    if (recognizer(targetType))
+                                    {
+                                        context.ReportDiagnostic(
+                                            Diagnostic.Create(
+                                                RuntimeComApisDoNotSupportSourceGeneratedCom,
+                                                diagnosticLocation,
+                                                operation.TargetMethod.ToMinimalDisplayString(operation.SemanticModel, operation.Syntax.SpanStart),
+                                                targetType.ToMinimalDisplayString(operation.SemanticModel, operation.Syntax.SpanStart)));
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }, OperationKind.Invocation);
+
+                static Func<IInvocationOperation, (ITypeSymbol Type, Location location)?> CreateArgumentTypeLookup(int ordinal) => invocation => invocation.GetArgumentByOrdinal(ordinal).Value switch
+                {
+                    IConversionOperation conversion => (conversion.Operand.Type, conversion.Operand.Syntax.GetLocation()),
+                    IOperation op => (op.Type, op.Syntax.GetLocation())
+                };
+
+                static Func<IInvocationOperation, (ITypeSymbol Type, Location location)?> CreateTypeArgumentTypeLookup(int ordinal) => invocation =>
+                {
+                    var type = invocation.TargetMethod.TypeArguments[ordinal];
+
+                    var invocationSyntax = (InvocationExpressionSyntax)invocation.Syntax;
+                    var expression = invocationSyntax.Expression;
+
+                    Location? location = null;
+
+                    if (expression.IsKind(SyntaxKind.SimpleMemberAccessExpression))
+                    {
+                        expression = ((MemberAccessExpressionSyntax)expression).Name;
+                    }
+
+                    if (expression.IsKind(SyntaxKind.GenericName))
+                    {
+                        location = ((GenericNameSyntax)expression).TypeArgumentList.Arguments[ordinal].GetLocation();
+                    }
+
+                    if (location is null)
+                    {
+                        // If we couldn't find the type argument in source, then it was inferred. Don't emit a warning for the inferred type argument.
+                        // We'll emit a warning for the argument that was passed in instead.
+                        return null;
+                    }
+
+                    return (type, location);
+                };
+
+                static Func<IInvocationOperation, (ITypeSymbol Type, Location location)?> CreateTypeOfArgumentTypeLookup(int ordinal) => invocation => invocation.GetArgumentByOrdinal(ordinal).Value switch
+                {
+                    ITypeOfOperation typeOf => (typeOf.TypeOperand, ((TypeOfExpressionSyntax)typeOf.Syntax).Type.GetLocation()),
+                    _ => null
+                };
+            });
+        }
+    }
+}
index 992c286..fed18f1 100644 (file)
@@ -1,8 +1,6 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-using System.Collections;
-using System.Collections.Generic;
 using System.Linq;
 using Microsoft.CodeAnalysis;
 using Microsoft.CodeAnalysis.CSharp;
index f8184a0..b58217a 100644 (file)
@@ -1,13 +1,11 @@
 // 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
 {
index cdfdbfa..d0334a4 100644 (file)
@@ -2,7 +2,6 @@
 // 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;
index a9116c3..c8d1f18 100644 (file)
   </ItemGroup>
 
   <ItemGroup>
-    <None Include="$(TargetPath)" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
-    <None Include="$(AssemblyName).props" Pack="true" PackagePath="build" />
     <Compile Include="..\Common\DefaultMarshallingInfoParser.cs" Link="Common\DefaultMarshallingInfoParser.cs" />
     <Compile Include="..\..\tests\Common\ExceptionMarshalling.cs" Link="Common\ExceptionMarshalling.cs" />
+    <Compile Include="$(CommonPath)\Roslyn\GetBestTypeByMetadataName.cs" Link="Common\Roslyn\GetBestTypeByMetadataName.cs" />
+    <Compile Include="..\Common\OperationExtensions.cs" Link="Common\OperationExtensions.cs" />
+    <Compile Include="..\Common\ConvertToSourceGeneratedInteropFixer.cs" Link="Common\ConvertToSourceGeneratedInteropFixer.cs" />
+    <Compile Include="..\Common\FixAllContextExtensions.cs" Link="Common\FixAllContextExtensions.cs" />
   </ItemGroup>
 
   <ItemGroup>
index 9faa09c..54b0864 100644 (file)
@@ -2,7 +2,6 @@
 // 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 System.Threading;
index c80290f..2fb9426 100644 (file)
@@ -1,7 +1,6 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-using System.Collections.Generic;
 using System.Collections.Immutable;
 using System.Diagnostics;
 using System.Linq;
index f8c42b2..36095b7 100644 (file)
@@ -1,12 +1,9 @@
 // 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
index f797fce..b1660ff 100644 (file)
   <data name="InvalidStringMarshallingConfigurationOnInterfaceMessage" xml:space="preserve">
     <value>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</value>
   </data>
+  <data name="ConvertToGeneratedComInterfaceDescription" xml:space="preserve">
+    <value>Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</value>
+  </data>
+  <data name="ConvertToGeneratedComInterfaceMayRequireCustomMarshalling" xml:space="preserve">
+    <value>Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</value>
+  </data>
+  <data name="ConvertToGeneratedComInterfaceMessage" xml:space="preserve">
+    <value>Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</value>
+  </data>
+  <data name="ConvertToGeneratedComInterfaceTitle" xml:space="preserve">
+    <value>Convert to 'GeneratedComInterface'</value>
+  </data>
+  <data name="AddGeneratedComClassAttributeDescription" xml:space="preserve">
+    <value>This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</value>
+  </data>
+  <data name="AddGeneratedComClassAttributeMessage" xml:space="preserve">
+    <value>Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</value>
+  </data>
+  <data name="AddGeneratedComClassAttributeTitle" xml:space="preserve">
+    <value>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</value>
+  </data>
+  <data name="ComHostingDoesNotSupportGeneratedComInterfaceDescription" xml:space="preserve">
+    <value>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</value>
+  </data>
+  <data name="ComHostingDoesNotSupportGeneratedComInterfaceMessage" xml:space="preserve">
+    <value>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</value>
+  </data>
+  <data name="ComHostingDoesNotSupportGeneratedComInterfaceTitle" xml:space="preserve">
+    <value>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</value>
+  </data>
+  <data name="AddGeneratedComClassAddUnsafe" xml:space="preserve">
+    <value>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</value>
+  </data>
+  <data name="ConvertToGeneratedComInterfaceAddUnsafe" xml:space="preserve">
+    <value>Convert to 'GeneratedComInterface' and allow unsafe code</value>
+  </data>
+  <data name="RuntimeComApisDoNotSupportSourceGeneratedComDescription" xml:space="preserve">
+    <value>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</value>
+  </data>
+  <data name="RuntimeComApisDoNotSupportSourceGeneratedComMessage" xml:space="preserve">
+    <value>The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</value>
+  </data>
+  <data name="RuntimeComApisDoNotSupportSourceGeneratedComTitle" xml:space="preserve">
+    <value>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</value>
+  </data>
+  <data name="ConvertComInterfaceMayProduceInvalidCode" xml:space="preserve">
+    <value>Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</value>
+  </data>
 </root>
\ No newline at end of file
index 0776aec..0194951 100644 (file)
@@ -2,6 +2,26 @@
 <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
   <file datatype="xml" source-language="en" target-language="cs" original="../Strings.resx">
     <body>
+      <trans-unit id="AddGeneratedComClassAddUnsafe">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeDescription">
+        <source>This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</source>
+        <target state="new">This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeMessage">
+        <source>Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</source>
+        <target state="new">Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeTitle">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="AnalysisFailedDescription">
         <source>The analysis required to generate code for this interface or method has failed due to an unexpected code pattern. If you are using new or unconventional syntax, consider using other syntax.</source>
         <target state="translated">Analýza požadovaná ke generování kódu pro toto rozhraní nebo metodu se nezdařila kvůli neočekávanému vzoru kódu. Pokud používáte novou nebo nekonvenční syntaxi, zvažte použití jiné syntaxe.</target>
         <target state="translated">Základnímu rozhraní COM se nepodařilo vygenerovat zdroj. ComInterfaceGenerator nevygeneruje zdroj pro toto rozhraní.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
+        <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceMessage">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceTitle">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="translated">Model COM vygenerovaný zdrojem bude ignorovat všechny nepodporované konfigurace.</target>
         <target state="translated">Zadaná konfigurace není podporována modelem COM generovaným zdrojem.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ConvertComInterfaceMayProduceInvalidCode">
+        <source>Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</source>
+        <target state="new">Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceAddUnsafe">
+        <source>Convert to 'GeneratedComInterface' and allow unsafe code</source>
+        <target state="new">Convert to 'GeneratedComInterface' and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceDescription">
+        <source>Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMayRequireCustomMarshalling">
+        <source>Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</source>
+        <target state="new">Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMessage">
+        <source>Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceTitle">
+        <source>Convert to 'GeneratedComInterface'</source>
+        <target state="new">Convert to 'GeneratedComInterface'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
         <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
         <target state="translated">Konfigurace „StringMarshalling“ a „StringMarshallingCustomType“ se musí shodovat se základním rozhraním COM.</target>
         <target state="translated">Zadané rozhraní je odvozeno ze dvou nebo více rozhraní s atributem GeneratedComInterfaceAttribute.</target>
         <note />
       </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComDescription">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComMessage">
+        <source>The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</source>
+        <target state="new">The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComTitle">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="TypeNotSupportedDescription">
         <source>For types that are not supported by source-generated COM, the resulting function pointer will rely on the underlying runtime to marshal the specified type.</source>
         <target state="translated">U typů, které nejsou podporovány modelem COM generovaným zdrojem, bude výsledný ukazatel funkce při zařazování zadaného typu spoléhat na základní modul runtime.</target>
index 3d7ec0c..b1f1441 100644 (file)
@@ -2,6 +2,26 @@
 <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
   <file datatype="xml" source-language="en" target-language="de" original="../Strings.resx">
     <body>
+      <trans-unit id="AddGeneratedComClassAddUnsafe">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeDescription">
+        <source>This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</source>
+        <target state="new">This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeMessage">
+        <source>Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</source>
+        <target state="new">Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeTitle">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="AnalysisFailedDescription">
         <source>The analysis required to generate code for this interface or method has failed due to an unexpected code pattern. If you are using new or unconventional syntax, consider using other syntax.</source>
         <target state="translated">Die Analyse, die erforderlich ist, um Code für diese Schnittstelle oder Methode zu erzeugen, ist aufgrund eines unerwarteten Codemusters fehlgeschlagen. Wenn Sie eine neue oder unkonventionelle Syntax verwenden, sollten Sie eine andere Syntax verwenden.</target>
         <target state="translated">Die Basis-COM-Schnittstelle konnte die Quelle nicht generieren. ComInterfaceGenerator generiert keine Quelle für diese Schnittstelle.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
+        <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceMessage">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceTitle">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="translated">Quellgeneriertes COM ignoriert alle Konfigurationen, die nicht unterstützt werden.</target>
         <target state="translated">Die angegebene Konfiguration wird vom quellgenerierten COM nicht unterstützt.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ConvertComInterfaceMayProduceInvalidCode">
+        <source>Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</source>
+        <target state="new">Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceAddUnsafe">
+        <source>Convert to 'GeneratedComInterface' and allow unsafe code</source>
+        <target state="new">Convert to 'GeneratedComInterface' and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceDescription">
+        <source>Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMayRequireCustomMarshalling">
+        <source>Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</source>
+        <target state="new">Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMessage">
+        <source>Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceTitle">
+        <source>Convert to 'GeneratedComInterface'</source>
+        <target state="new">Convert to 'GeneratedComInterface'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
         <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
         <target state="translated">Die Konfiguration von "StringMarshalling" und "StringMarshallingCustomType" muss mit der COM-Basisschnittstelle übereinstimmen.</target>
         <target state="translated">Die angegebene Schnittstelle wird von mindestens zwei Schnittstellen abgeleitet, die "GeneratedComInterfaceAttribute" zugeordnet sind.</target>
         <note />
       </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComDescription">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComMessage">
+        <source>The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</source>
+        <target state="new">The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComTitle">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="TypeNotSupportedDescription">
         <source>For types that are not supported by source-generated COM, the resulting function pointer will rely on the underlying runtime to marshal the specified type.</source>
         <target state="translated">Bei Typen, die vom quellgenerierten COM nicht unterstützt werden, basiert der resultierende Funktionszeiger auf der zugrunde liegenden Laufzeit, um den angegebenen Typ zu marshallen.</target>
index a24178f..3fa88a7 100644 (file)
@@ -2,6 +2,26 @@
 <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
   <file datatype="xml" source-language="en" target-language="es" original="../Strings.resx">
     <body>
+      <trans-unit id="AddGeneratedComClassAddUnsafe">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeDescription">
+        <source>This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</source>
+        <target state="new">This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeMessage">
+        <source>Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</source>
+        <target state="new">Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeTitle">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="AnalysisFailedDescription">
         <source>The analysis required to generate code for this interface or method has failed due to an unexpected code pattern. If you are using new or unconventional syntax, consider using other syntax.</source>
         <target state="translated">Se ha producido un error en el análisis necesario para generar código para esta interfaz o método debido a un patrón de código inesperado. Si está usando sintaxis nueva o no convencional, considere la posibilidad de usar otra sintaxis.</target>
         <target state="translated">La interfaz COM base no pudo generar el origen. ComInterfaceGenerator no generará el origen para esta interfaz.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
+        <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceMessage">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceTitle">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="translated">COM generado por el origen omitirá cualquier configuración que no se admita.</target>
         <target state="translated">COM generado por origen no admite la configuración especificada.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ConvertComInterfaceMayProduceInvalidCode">
+        <source>Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</source>
+        <target state="new">Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceAddUnsafe">
+        <source>Convert to 'GeneratedComInterface' and allow unsafe code</source>
+        <target state="new">Convert to 'GeneratedComInterface' and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceDescription">
+        <source>Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMayRequireCustomMarshalling">
+        <source>Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</source>
+        <target state="new">Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMessage">
+        <source>Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceTitle">
+        <source>Convert to 'GeneratedComInterface'</source>
+        <target state="new">Convert to 'GeneratedComInterface'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
         <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
         <target state="translated">La configuración de "StringMarshalling" y "StringMarshallingCustomType" debe coincidir con la interfaz COM base.</target>
         <target state="translated">La interfaz especificada deriva de dos o más interfaces con atributos "GeneratedComInterfaceAttribute".</target>
         <note />
       </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComDescription">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComMessage">
+        <source>The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</source>
+        <target state="new">The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComTitle">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="TypeNotSupportedDescription">
         <source>For types that are not supported by source-generated COM, the resulting function pointer will rely on the underlying runtime to marshal the specified type.</source>
         <target state="translated">Para los tipos que no son compatibles con COM generado por el origen, el puntero de función resultante se basará en el tiempo de ejecución subyacente para serializar el tipo especificado.</target>
index 97bdf01..e76c3db 100644 (file)
@@ -2,6 +2,26 @@
 <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
   <file datatype="xml" source-language="en" target-language="fr" original="../Strings.resx">
     <body>
+      <trans-unit id="AddGeneratedComClassAddUnsafe">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeDescription">
+        <source>This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</source>
+        <target state="new">This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeMessage">
+        <source>Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</source>
+        <target state="new">Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeTitle">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="AnalysisFailedDescription">
         <source>The analysis required to generate code for this interface or method has failed due to an unexpected code pattern. If you are using new or unconventional syntax, consider using other syntax.</source>
         <target state="translated">L’analyse requise pour générer du code pour cette interface ou cette méthode a échoué en raison d’un modèle de code inattendu. Si vous utilisez une syntaxe nouvelle ou syntaxe correcte, utilisez une autre syntaxe.</target>
         <target state="translated">L’interface COM de base n’a pas pu générer la source. ComInterfaceGenerator ne génère pas de source pour cette interface.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
+        <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceMessage">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceTitle">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="translated">COM généré par la source ignore toute configuration qui n’est pas prise en charge.</target>
         <target state="translated">La configuration spécifiée n’est pas prise en charge par com généré par la source.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ConvertComInterfaceMayProduceInvalidCode">
+        <source>Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</source>
+        <target state="new">Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceAddUnsafe">
+        <source>Convert to 'GeneratedComInterface' and allow unsafe code</source>
+        <target state="new">Convert to 'GeneratedComInterface' and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceDescription">
+        <source>Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMayRequireCustomMarshalling">
+        <source>Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</source>
+        <target state="new">Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMessage">
+        <source>Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceTitle">
+        <source>Convert to 'GeneratedComInterface'</source>
+        <target state="new">Convert to 'GeneratedComInterface'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
         <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
         <target state="translated">La configuration de « StringMarshalling » et de « StringMarshallingCustomType » doit correspondre à l’interface COM de base.</target>
         <target state="translated">L’interface spécifiée dérive de deux ou plusieurs interfaces avec attribut 'GeneratedComInterfaceAttribute'.</target>
         <note />
       </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComDescription">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComMessage">
+        <source>The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</source>
+        <target state="new">The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComTitle">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="TypeNotSupportedDescription">
         <source>For types that are not supported by source-generated COM, the resulting function pointer will rely on the underlying runtime to marshal the specified type.</source>
         <target state="translated">Pour les types qui ne sont pas pris en charge par com généré par la source, le pointeur de fonction résultant s’appuie sur le runtime sous-jacent pour marshaler le type spécifié.</target>
index ae11d9f..5806cfc 100644 (file)
@@ -2,6 +2,26 @@
 <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
   <file datatype="xml" source-language="en" target-language="it" original="../Strings.resx">
     <body>
+      <trans-unit id="AddGeneratedComClassAddUnsafe">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeDescription">
+        <source>This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</source>
+        <target state="new">This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeMessage">
+        <source>Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</source>
+        <target state="new">Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeTitle">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="AnalysisFailedDescription">
         <source>The analysis required to generate code for this interface or method has failed due to an unexpected code pattern. If you are using new or unconventional syntax, consider using other syntax.</source>
         <target state="translated">L'analisi necessaria per generare il codice per questa interfaccia o per questo metodo non è riuscita a causa di un modello di codice imprevisto. Se si usa una sintassi nuova o non intenzionale, provare a usare un'altra sintassi.</target>
         <target state="translated">L'interfaccia COM di base non è riuscita a generare l'origine. ComInterfaceGenerator non genererà l'origine per questa interfaccia.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
+        <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceMessage">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceTitle">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="translated">I COM generati dall'origine ignoreranno qualsiasi configurazione non supportata.</target>
         <target state="translated">La configurazione specificata non è supportata dai COM generati dall'origine.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ConvertComInterfaceMayProduceInvalidCode">
+        <source>Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</source>
+        <target state="new">Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceAddUnsafe">
+        <source>Convert to 'GeneratedComInterface' and allow unsafe code</source>
+        <target state="new">Convert to 'GeneratedComInterface' and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceDescription">
+        <source>Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMayRequireCustomMarshalling">
+        <source>Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</source>
+        <target state="new">Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMessage">
+        <source>Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceTitle">
+        <source>Convert to 'GeneratedComInterface'</source>
+        <target state="new">Convert to 'GeneratedComInterface'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
         <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
         <target state="translated">La configurazione di 'StringMarshalling' e 'StringMarshallingCustomType' deve corrispondere all'interfaccia COM di base.</target>
         <target state="translated">L'interfaccia specificata deriva da due o più interfacce con attributi 'GeneratedComInterfaceAttribute'.</target>
         <note />
       </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComDescription">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComMessage">
+        <source>The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</source>
+        <target state="new">The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComTitle">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="TypeNotSupportedDescription">
         <source>For types that are not supported by source-generated COM, the resulting function pointer will rely on the underlying runtime to marshal the specified type.</source>
         <target state="translated">Per i tipi non supportati dai COM generati dall'origine, il puntatore funzione risultante si baserà sul runtime sottostante per effettuare il marshalling del tipo specificato.</target>
index 042d3ac..8765737 100644 (file)
@@ -2,6 +2,26 @@
 <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
   <file datatype="xml" source-language="en" target-language="ja" original="../Strings.resx">
     <body>
+      <trans-unit id="AddGeneratedComClassAddUnsafe">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeDescription">
+        <source>This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</source>
+        <target state="new">This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeMessage">
+        <source>Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</source>
+        <target state="new">Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeTitle">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="AnalysisFailedDescription">
         <source>The analysis required to generate code for this interface or method has failed due to an unexpected code pattern. If you are using new or unconventional syntax, consider using other syntax.</source>
         <target state="translated">予期しないコード パターンのため、このインターフェイスまたはメソッドのコードを生成するために必要な分析が失敗しました。新しい構文または従来とは異なる構文を使用している場合は、他の構文の使用を検討してください。</target>
         <target state="translated">ベース COM インターフェイスはソースを生成できませんでした。ComInterfaceGenerator は、このインターフェイスのソースを生成しません。</target>
         <note />
       </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
+        <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceMessage">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceTitle">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="translated">ソース生成済みの COM は、サポートされていない構成を無視します。</target>
         <target state="translated">指定された構成は、ソース生成済みの COM ではサポートされていません。</target>
         <note />
       </trans-unit>
+      <trans-unit id="ConvertComInterfaceMayProduceInvalidCode">
+        <source>Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</source>
+        <target state="new">Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceAddUnsafe">
+        <source>Convert to 'GeneratedComInterface' and allow unsafe code</source>
+        <target state="new">Convert to 'GeneratedComInterface' and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceDescription">
+        <source>Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMayRequireCustomMarshalling">
+        <source>Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</source>
+        <target state="new">Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMessage">
+        <source>Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceTitle">
+        <source>Convert to 'GeneratedComInterface'</source>
+        <target state="new">Convert to 'GeneratedComInterface'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
         <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
         <target state="translated">'StringMarshalling' および 'StringMarshallingCustomType' の構成は、ベース COM インターフェイスと一致する必要があります。</target>
         <target state="translated">指定されたインターフェイスは、2 つ以上の 'GeneratedComInterfaceAttribute' 属性インターフェイスから派生しています。</target>
         <note />
       </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComDescription">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComMessage">
+        <source>The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</source>
+        <target state="new">The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComTitle">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="TypeNotSupportedDescription">
         <source>For types that are not supported by source-generated COM, the resulting function pointer will rely on the underlying runtime to marshal the specified type.</source>
         <target state="translated">ソース生成済みの COM でサポートされていない型である場合、生成された関数ポインターは、基礎となるなるランタイムに依存して、指定された型をマーシャリングします。</target>
index a13812c..2062b2f 100644 (file)
@@ -2,6 +2,26 @@
 <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
   <file datatype="xml" source-language="en" target-language="ko" original="../Strings.resx">
     <body>
+      <trans-unit id="AddGeneratedComClassAddUnsafe">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeDescription">
+        <source>This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</source>
+        <target state="new">This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeMessage">
+        <source>Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</source>
+        <target state="new">Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeTitle">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="AnalysisFailedDescription">
         <source>The analysis required to generate code for this interface or method has failed due to an unexpected code pattern. If you are using new or unconventional syntax, consider using other syntax.</source>
         <target state="translated">예기치 않은 코드 패턴으로 인해 이 인터페이스 또는 메서드에 대한 코드를 생성하는 데 필요한 분석이 실패했습니다. 새 구문 또는 이례적 구문을 사용하는 경우 다른 구문을 사용하는 것이 좋습니다.</target>
         <target state="translated">기본 COM 인터페이스에서 원본을 생성하지 못했습니다. ComInterfaceGenerator는 이 인터페이스에 대한 원본을 생성하지 않습니다.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
+        <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceMessage">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceTitle">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="translated">소스 생성 COM은 지원되지 않는 구성을 무시합니다.</target>
         <target state="translated">지정된 구성은 원본 생성 COM에서 지원되지 않습니다.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ConvertComInterfaceMayProduceInvalidCode">
+        <source>Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</source>
+        <target state="new">Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceAddUnsafe">
+        <source>Convert to 'GeneratedComInterface' and allow unsafe code</source>
+        <target state="new">Convert to 'GeneratedComInterface' and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceDescription">
+        <source>Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMayRequireCustomMarshalling">
+        <source>Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</source>
+        <target state="new">Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMessage">
+        <source>Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceTitle">
+        <source>Convert to 'GeneratedComInterface'</source>
+        <target state="new">Convert to 'GeneratedComInterface'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
         <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
         <target state="translated">'StringMarshalling' 및 'StringMarshallingCustomType'의 구성은 기본 COM 인터페이스와 일치해야 합니다.</target>
         <target state="translated">지정한 인터페이스는 두 개 이상의 'GeneratedComInterfaceAttribute' 특성 인터페이스에서 파생됩니다.</target>
         <note />
       </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComDescription">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComMessage">
+        <source>The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</source>
+        <target state="new">The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComTitle">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="TypeNotSupportedDescription">
         <source>For types that are not supported by source-generated COM, the resulting function pointer will rely on the underlying runtime to marshal the specified type.</source>
         <target state="translated">원본 생성 COM에서 지원하지 않는 형식의 경우 결과 함수 포인터는 기본 런타임을 사용하여 지정된 형식을 마샬링합니다.</target>
index 63f9240..62d7ce1 100644 (file)
@@ -2,6 +2,26 @@
 <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
   <file datatype="xml" source-language="en" target-language="pl" original="../Strings.resx">
     <body>
+      <trans-unit id="AddGeneratedComClassAddUnsafe">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeDescription">
+        <source>This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</source>
+        <target state="new">This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeMessage">
+        <source>Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</source>
+        <target state="new">Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeTitle">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="AnalysisFailedDescription">
         <source>The analysis required to generate code for this interface or method has failed due to an unexpected code pattern. If you are using new or unconventional syntax, consider using other syntax.</source>
         <target state="translated">Analiza wymagana do wygenerowania kodu dla tego interfejsu lub metody nie powiodła się z powodu nieoczekiwanego wzorca kodu. Jeśli używasz nowej składni lub nieszablonowej składni, rozważ użycie innej składni.</target>
         <target state="translated">Podstawowy interfejs COM nie może wygenerować źródła. Program ComInterfaceGenerator nie wygeneruje źródła dla tego interfejsu.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
+        <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceMessage">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceTitle">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="translated">COM wygenerowany przez źródło zignoruje każdą konfigurację, która nie jest obsługiwana.</target>
         <target state="translated">Określona konfiguracja nie jest obsługiwana przez COM wygenerowany przez źródło.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ConvertComInterfaceMayProduceInvalidCode">
+        <source>Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</source>
+        <target state="new">Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceAddUnsafe">
+        <source>Convert to 'GeneratedComInterface' and allow unsafe code</source>
+        <target state="new">Convert to 'GeneratedComInterface' and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceDescription">
+        <source>Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMayRequireCustomMarshalling">
+        <source>Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</source>
+        <target state="new">Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMessage">
+        <source>Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceTitle">
+        <source>Convert to 'GeneratedComInterface'</source>
+        <target state="new">Convert to 'GeneratedComInterface'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
         <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
         <target state="translated">Konfiguracja elementów „StringMarssourceing” i „StringMarsxtingCustomType” musi być zgodna z podstawowym interfejsem COM.</target>
         <target state="translated">Określony interfejs pochodzi z co najmniej dwóch interfejsów z atrybutem „GeneratedComInterfaceAttribute”.</target>
         <note />
       </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComDescription">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComMessage">
+        <source>The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</source>
+        <target state="new">The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComTitle">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="TypeNotSupportedDescription">
         <source>For types that are not supported by source-generated COM, the resulting function pointer will rely on the underlying runtime to marshal the specified type.</source>
         <target state="translated">W przypadku typów, które nie są obsługiwane przez COM wygenerowany przez źródło, wynikowy wskaźnik funkcji będzie polegał na bazowym środowisku uruchomieniowym w celu skierowania określonego typu.</target>
index 9ce3756..5486a45 100644 (file)
@@ -2,6 +2,26 @@
 <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
   <file datatype="xml" source-language="en" target-language="pt-BR" original="../Strings.resx">
     <body>
+      <trans-unit id="AddGeneratedComClassAddUnsafe">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeDescription">
+        <source>This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</source>
+        <target state="new">This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeMessage">
+        <source>Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</source>
+        <target state="new">Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeTitle">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="AnalysisFailedDescription">
         <source>The analysis required to generate code for this interface or method has failed due to an unexpected code pattern. If you are using new or unconventional syntax, consider using other syntax.</source>
         <target state="translated">A análise necessária para gerar código para essa interface ou método falhou devido a um padrão de código inesperado. Se você estiver usando sintaxe nova ou não convencional, considere usar outra sintaxe.</target>
         <target state="translated">A interface COM base falhou ao gerar a fonte. ComInterfaceGenerator não irá gerar fonte para esta interface.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
+        <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceMessage">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceTitle">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="translated">Um COM gerado pela origem ignorará qualquer configuração sem suporte.</target>
         <target state="translated">Um COM gerado pela origem não dá suporte a uma configuração especificada.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ConvertComInterfaceMayProduceInvalidCode">
+        <source>Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</source>
+        <target state="new">Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceAddUnsafe">
+        <source>Convert to 'GeneratedComInterface' and allow unsafe code</source>
+        <target state="new">Convert to 'GeneratedComInterface' and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceDescription">
+        <source>Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMayRequireCustomMarshalling">
+        <source>Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</source>
+        <target state="new">Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMessage">
+        <source>Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceTitle">
+        <source>Convert to 'GeneratedComInterface'</source>
+        <target state="new">Convert to 'GeneratedComInterface'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
         <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
         <target state="translated">A configuração de 'StringMarshalling' e 'StringMarshallingCustomType' deve corresponder à interface COM base.</target>
         <target state="translated">A interface especificada deriva de duas ou mais interfaces atribuídas a 'GeneratedComInterfaceAttribute'.</target>
         <note />
       </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComDescription">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComMessage">
+        <source>The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</source>
+        <target state="new">The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComTitle">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="TypeNotSupportedDescription">
         <source>For types that are not supported by source-generated COM, the resulting function pointer will rely on the underlying runtime to marshal the specified type.</source>
         <target state="translated">Para tipos sem suporte para um COM gerado pela origem, o ponteiro de função resultante dependerá do tempo de execução subjacente para realizar marshaling no tipo especificado.</target>
index 01ab6e8..12e76c9 100644 (file)
@@ -2,6 +2,26 @@
 <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
   <file datatype="xml" source-language="en" target-language="ru" original="../Strings.resx">
     <body>
+      <trans-unit id="AddGeneratedComClassAddUnsafe">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeDescription">
+        <source>This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</source>
+        <target state="new">This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeMessage">
+        <source>Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</source>
+        <target state="new">Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeTitle">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="AnalysisFailedDescription">
         <source>The analysis required to generate code for this interface or method has failed due to an unexpected code pattern. If you are using new or unconventional syntax, consider using other syntax.</source>
         <target state="translated">Произошел сбой анализа, необходимого для создания кода для этого интерфейса или метода, из-за непредвиденного шаблона кода. Если вы используйте новый или нестандартный синтаксис, попробуйте использовать другой синтаксис.</target>
         <target state="translated">Базовому COM-интерфейсу не удалось создать источник. ComInterfaceGenerator не будет создавать источник для этого интерфейса.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
+        <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceMessage">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceTitle">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="translated">Модель COM генератора исходного кода будет игнорировать любую неподдерживаемую конфигурацию.</target>
         <target state="translated">Указанная конфигурация не поддерживается моделью COM генератора исходного кода.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ConvertComInterfaceMayProduceInvalidCode">
+        <source>Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</source>
+        <target state="new">Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceAddUnsafe">
+        <source>Convert to 'GeneratedComInterface' and allow unsafe code</source>
+        <target state="new">Convert to 'GeneratedComInterface' and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceDescription">
+        <source>Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMayRequireCustomMarshalling">
+        <source>Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</source>
+        <target state="new">Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMessage">
+        <source>Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceTitle">
+        <source>Convert to 'GeneratedComInterface'</source>
+        <target state="new">Convert to 'GeneratedComInterface'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
         <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
         <target state="translated">Конфигурация "StringMarshalling" и "StringMarshallingCustomType" должна соответствовать базовому COM-интерфейсу.</target>
         <target state="translated">Указанный интерфейс является производным от двух или более интерфейсов с атрибутом "GeneratedComInterfaceAttribute".</target>
         <note />
       </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComDescription">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComMessage">
+        <source>The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</source>
+        <target state="new">The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComTitle">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="TypeNotSupportedDescription">
         <source>For types that are not supported by source-generated COM, the resulting function pointer will rely on the underlying runtime to marshal the specified type.</source>
         <target state="translated">Для типов, которые не поддерживаются моделью COM генератора исходного кода, результирующий указатель на функцию будет выполнять маршалинг указанного типа на базе используемой среды выполнения.</target>
index a14f019..c40fff4 100644 (file)
@@ -2,6 +2,26 @@
 <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
   <file datatype="xml" source-language="en" target-language="tr" original="../Strings.resx">
     <body>
+      <trans-unit id="AddGeneratedComClassAddUnsafe">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeDescription">
+        <source>This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</source>
+        <target state="new">This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeMessage">
+        <source>Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</source>
+        <target state="new">Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeTitle">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="AnalysisFailedDescription">
         <source>The analysis required to generate code for this interface or method has failed due to an unexpected code pattern. If you are using new or unconventional syntax, consider using other syntax.</source>
         <target state="translated">Bu arabirim veya yöntem için kod oluşturmak için gerekli analiz beklenmeyen bir kod deseni nedeniyle başarısız oldu. Yeni veya alışılmadık bir söz dizimi kullanıyorsanız başka bir söz dizimi kullanmayı deneyin.</target>
         <target state="translated">Temel COM arabirimi kaynak oluşturamadı. ComInterfaceGenerator bu arabirim için kaynak oluşturamaz.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
+        <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceMessage">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceTitle">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="translated">Kaynak tarafından oluşturulan COM, desteklenmeyen herhangi bir yapılandırmayı yoksayar.</target>
         <target state="translated">Belirtilen yapılandırma, kaynak tarafından oluşturulan COM tarafından desteklenmiyor.</target>
         <note />
       </trans-unit>
+      <trans-unit id="ConvertComInterfaceMayProduceInvalidCode">
+        <source>Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</source>
+        <target state="new">Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceAddUnsafe">
+        <source>Convert to 'GeneratedComInterface' and allow unsafe code</source>
+        <target state="new">Convert to 'GeneratedComInterface' and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceDescription">
+        <source>Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMayRequireCustomMarshalling">
+        <source>Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</source>
+        <target state="new">Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMessage">
+        <source>Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceTitle">
+        <source>Convert to 'GeneratedComInterface'</source>
+        <target state="new">Convert to 'GeneratedComInterface'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
         <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
         <target state="translated">'StringMarshalling' ve 'StringMarshallingCustomType' yapılandırması temel COM arabirimiyle eşleşmelidir.</target>
         <target state="translated">Belirtilen arabirim 'GeneratedComInterfaceAttribute' özniteliğine sahip iki veya daha fazla arabirimden türetildi.</target>
         <note />
       </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComDescription">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComMessage">
+        <source>The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</source>
+        <target state="new">The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComTitle">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="TypeNotSupportedDescription">
         <source>For types that are not supported by source-generated COM, the resulting function pointer will rely on the underlying runtime to marshal the specified type.</source>
         <target state="translated">Kaynak tarafından oluşturulan COM tarafından desteklenmeyen türler için, ortaya çıkan işlev işaretçisi, belirtilen türü sıralamak için temeldeki çalışma zamanına güvenir.</target>
index 5e68280..4f4d31c 100644 (file)
@@ -2,6 +2,26 @@
 <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
   <file datatype="xml" source-language="en" target-language="zh-Hans" original="../Strings.resx">
     <body>
+      <trans-unit id="AddGeneratedComClassAddUnsafe">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeDescription">
+        <source>This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</source>
+        <target state="new">This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeMessage">
+        <source>Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</source>
+        <target state="new">Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeTitle">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="AnalysisFailedDescription">
         <source>The analysis required to generate code for this interface or method has failed due to an unexpected code pattern. If you are using new or unconventional syntax, consider using other syntax.</source>
         <target state="translated">由于意外的代码模式,为此接口或方法生成代码所需的分析失败。如果你使用的是新语法或非常规语法,请考虑使用其他语法。</target>
         <target state="translated">基本 COM 接口无法生成源。ComInterfaceGenerator 不会为此接口生成源。</target>
         <note />
       </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
+        <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceMessage">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceTitle">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="translated">源生成的 COM 将忽略任何不受支持的配置。</target>
         <target state="translated">源生成的 COM 不支持指定的配置。</target>
         <note />
       </trans-unit>
+      <trans-unit id="ConvertComInterfaceMayProduceInvalidCode">
+        <source>Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</source>
+        <target state="new">Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceAddUnsafe">
+        <source>Convert to 'GeneratedComInterface' and allow unsafe code</source>
+        <target state="new">Convert to 'GeneratedComInterface' and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceDescription">
+        <source>Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMayRequireCustomMarshalling">
+        <source>Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</source>
+        <target state="new">Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMessage">
+        <source>Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceTitle">
+        <source>Convert to 'GeneratedComInterface'</source>
+        <target state="new">Convert to 'GeneratedComInterface'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
         <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
         <target state="translated">"StringMarshalling" 和 "StringMarshallingCustomType" 的配置必须与基本 COM 接口匹配。</target>
         <target state="translated">指定的接口派生自两个或更多“GeneratedComInterfaceAttribute”特性化接口。</target>
         <note />
       </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComDescription">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComMessage">
+        <source>The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</source>
+        <target state="new">The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComTitle">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="TypeNotSupportedDescription">
         <source>For types that are not supported by source-generated COM, the resulting function pointer will rely on the underlying runtime to marshal the specified type.</source>
         <target state="translated">对于源生成的 COM 不支持的类型,生成的函数指针将依赖基础运行时来封送指定的类型。</target>
index e9d2af2..c47e7b9 100644 (file)
@@ -2,6 +2,26 @@
 <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
   <file datatype="xml" source-language="en" target-language="zh-Hant" original="../Strings.resx">
     <body>
+      <trans-unit id="AddGeneratedComClassAddUnsafe">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeDescription">
+        <source>This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</source>
+        <target state="new">This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeMessage">
+        <source>Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</source>
+        <target state="new">Add the 'GeneratedComClassAttribute' to '{0}' to enable passing objects of type '{0}' to COM</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="AddGeneratedComClassAttributeTitle">
+        <source>Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</source>
+        <target state="new">Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="AnalysisFailedDescription">
         <source>The analysis required to generate code for this interface or method has failed due to an unexpected code pattern. If you are using new or unconventional syntax, consider using other syntax.</source>
         <target state="translated">產生此介面或方法程式碼所需的分析失敗,因為有未預期的程式碼模式。如果您使用的是新語法或非常規語法,請考慮使用其他語法。</target>
         <target state="translated">基底 COM 介面無法產生來源。ComInterfaceGenerator 不會產生此介面的來源。</target>
         <note />
       </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
+        <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceMessage">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'. Change any COM exposed interfaces implemented by '{0}' to use the 'System.Runtime.InteropServices.ComVisibleAttribute' instead</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceTitle">
+        <source>.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</source>
+        <target state="new">.NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="translated">来源產生的 COM 將會略過任何不支援的設定。</target>
         <target state="translated">来源產生的 COM 不支援指定的設定。</target>
         <note />
       </trans-unit>
+      <trans-unit id="ConvertComInterfaceMayProduceInvalidCode">
+        <source>Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</source>
+        <target state="new">Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceAddUnsafe">
+        <source>Convert to 'GeneratedComInterface' and allow unsafe code</source>
+        <target state="new">Convert to 'GeneratedComInterface' and allow unsafe code</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceDescription">
+        <source>Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMayRequireCustomMarshalling">
+        <source>Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</source>
+        <target state="new">Converting this API to 'GeneratedComInterfaceAttribute' will require additional code to provide custom marshallers for some parameters.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceMessage">
+        <source>Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</source>
+        <target state="new">Mark the type '{0}' with 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="ConvertToGeneratedComInterfaceTitle">
+        <source>Convert to 'GeneratedComInterface'</source>
+        <target state="new">Convert to 'GeneratedComInterface'</target>
+        <note />
+      </trans-unit>
       <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
         <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
         <target state="translated">'StringMarshalling' 和 'StringMarshallingCustomType' 的設定必須和基底 COM 介面相符。</target>
         <target state="translated">指定的介面衍生自兩個或兩個以上的 'GeneratedComInterfaceAttribute'-屬性介面。</target>
         <note />
       </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComDescription">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComMessage">
+        <source>The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</source>
+        <target state="new">The method '{0}' only supports runtime-based COM interop and will not work with type '{1}'</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="RuntimeComApisDoNotSupportSourceGeneratedComTitle">
+        <source>COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</source>
+        <target state="new">COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM</target>
+        <note />
+      </trans-unit>
       <trans-unit id="TypeNotSupportedDescription">
         <source>For types that are not supported by source-generated COM, the resulting function pointer will rely on the underlying runtime to marshal the specified type.</source>
         <target state="translated">對於來源產生的 COM 不支援的類型,產生的函式指標將依賴基礎執行階段來封送處理指定的類型。</target>
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/ConvertToSourceGeneratedInteropFixer.cs b/src/libraries/System.Runtime.InteropServices/gen/Common/ConvertToSourceGeneratedInteropFixer.cs
new file mode 100644 (file)
index 0000000..7422d08
--- /dev/null
@@ -0,0 +1,263 @@
+// 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.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CodeActions;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Editing;
+
+namespace Microsoft.Interop.Analyzers
+{
+    public abstract class ConvertToSourceGeneratedInteropFixer : CodeFixProvider
+    {
+        public sealed override FixAllProvider GetFixAllProvider() => CustomFixAllProvider.Instance;
+
+        protected abstract string BaseEquivalenceKey { get; }
+
+        protected virtual IEnumerable<ConvertToSourceGeneratedInteropFix> CreateAllFixesForDiagnosticOptions(SyntaxNode node, ImmutableDictionary<string, Option> options)
+        {
+            // By default, we only have one fix for the options specified from the diagnostic.
+            yield return new ConvertToSourceGeneratedInteropFix(CreateFixForSelectedOptions(node, options), options);
+        }
+
+        protected abstract Func<DocumentEditor, CancellationToken, Task> CreateFixForSelectedOptions(SyntaxNode node, ImmutableDictionary<string, Option> selectedOptions);
+
+        protected abstract string GetDiagnosticTitle(ImmutableDictionary<string, Option> selectedOptions);
+
+        /// <summary>
+        /// A basic string-serializable option mechanism to enable the same fixer to be used for diagnostics with slightly different properties.
+        /// </summary>
+        public abstract record Option
+        {
+            private protected Option()
+            {
+            }
+
+            public const string AllowUnsafe = nameof(AllowUnsafe);
+            public const string MayRequireAdditionalWork = nameof(MayRequireAdditionalWork);
+
+            public sealed record Bool(bool Value) : Option
+            {
+                public override string ToString() => $"b:{Value};";
+            }
+
+            public sealed record String(string Value) : Option
+            {
+                public override string ToString() => $"s:{Value};";
+            }
+
+            public static ImmutableDictionary<string, Option> ParseOptionsFromEquivalenceKey(string equivalenceKey)
+            {
+                ImmutableDictionary<string, Option>.Builder options = ImmutableDictionary.CreateBuilder<string, Option>();
+                // The first ';' separates the base equivalence key from the options
+                foreach (string option in equivalenceKey.Split(';').Skip(0))
+                {
+                    string[] optionKeyAndValue = option.Split('=');
+                    if (optionKeyAndValue.Length != 2 || optionKeyAndValue[1].Length < 3)
+                    {
+                        continue;
+                    }
+
+                    string type = optionKeyAndValue[1].Substring(0, 2);
+                    string value = optionKeyAndValue[1].Substring(2);
+                    if (type == "b:")
+                    {
+                        options.Add(optionKeyAndValue[0], new Bool(bool.Parse(value)));
+                    }
+                    else if (type == "s:")
+                    {
+                        options.Add(optionKeyAndValue[0], new String(value));
+                    }
+                }
+
+                return options.ToImmutable();
+            }
+
+            public static string CreateEquivalenceKeyFromOptions(string baseEquivalenceKey, ImmutableDictionary<string, Option> options)
+            {
+                StringBuilder equivalenceKeyBuilder = new(baseEquivalenceKey);
+                foreach (var option in options.OrderBy(item => item.Key))
+                {
+                    equivalenceKeyBuilder.Append($";{option.Key}={option.Value}");
+                }
+                return equivalenceKeyBuilder.ToString();
+            }
+        }
+
+        protected abstract ImmutableDictionary<string, Option> ParseOptionsFromDiagnostic(Diagnostic diagnostic);
+
+        private static async Task<Solution> ApplyActionAndEnableUnsafe(Solution solution, DocumentId documentId, Func<DocumentEditor, CancellationToken, Task> documentBasedFix, CancellationToken ct)
+        {
+            var editor = new SolutionEditor(solution);
+            var docEditor = await editor.GetDocumentEditorAsync(documentId, ct).ConfigureAwait(false);
+            await documentBasedFix(docEditor, ct).ConfigureAwait(false);
+
+            var docProjectId = documentId.ProjectId;
+            var updatedSolution = editor.GetChangedSolution();
+            return AddUnsafe(updatedSolution, updatedSolution.GetProject(docProjectId));
+        }
+
+        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
+        {
+            // Get the syntax root and semantic model
+            Document doc = context.Document;
+            SyntaxNode? root = await doc.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
+            if (root == null)
+                return;
+
+            SyntaxNode node = root.FindNode(context.Span);
+
+            bool enableUnsafe = doc.Project.CompilationOptions is CSharpCompilationOptions { AllowUnsafe: false };
+            foreach (Diagnostic diagnostic in context.Diagnostics)
+            {
+                var options = ParseOptionsFromDiagnostic(diagnostic);
+                foreach (var fix in CreateAllFixesForDiagnosticOptions(node, options))
+                {
+                    if (enableUnsafe)
+                    {
+                        var selectedOptions = fix.SelectedOptions.Add(Option.AllowUnsafe, new Option.Bool(true));
+
+                        context.RegisterCodeFix(
+                            CodeAction.Create(
+                                GetDiagnosticTitle(selectedOptions),
+                                ct => ApplyActionAndEnableUnsafe(doc.Project.Solution, doc.Id, fix.ApplyFix, ct),
+                                Option.CreateEquivalenceKeyFromOptions(BaseEquivalenceKey, selectedOptions)),
+                            diagnostic);
+                    }
+                    else
+                    {
+                        context.RegisterCodeFix(
+                            CodeAction.Create(
+                                GetDiagnosticTitle(fix.SelectedOptions),
+                                async ct =>
+                                {
+                                    DocumentEditor editor = await DocumentEditor.CreateAsync(doc, ct).ConfigureAwait(false);
+
+                                    await fix.ApplyFix(editor, ct).ConfigureAwait(false);
+
+                                    return editor.GetChangedDocument();
+                                },
+                                Option.CreateEquivalenceKeyFromOptions(BaseEquivalenceKey, fix.SelectedOptions)),
+                            diagnostic);
+                    }
+                }
+            }
+        }
+
+        protected record struct ConvertToSourceGeneratedInteropFix(Func<DocumentEditor, CancellationToken, Task> ApplyFix, ImmutableDictionary<string, Option> SelectedOptions);
+
+        private sealed class CustomFixAllProvider : FixAllProvider
+        {
+            public static readonly CustomFixAllProvider Instance = new();
+            public override async Task<CodeAction?> GetFixAsync(FixAllContext fixAllContext)
+            {
+                var options = Option.ParseOptionsFromEquivalenceKey(fixAllContext.CodeActionEquivalenceKey);
+                var codeFixProvider = (ConvertToSourceGeneratedInteropFixer)fixAllContext.CodeFixProvider;
+
+                bool addUnsafe = options.TryGetValue(Option.AllowUnsafe, out Option allowUnsafeOption) && allowUnsafeOption is Option.Bool(true);
+
+                bool includeFixesWithAdditionalWork = options.TryGetValue(Option.MayRequireAdditionalWork, out Option includeFixesWithAdditionalWorkOption) && includeFixesWithAdditionalWorkOption is Option.Bool(true);
+                ImmutableArray<Diagnostic> diagnosticsInScope = await fixAllContext.GetDiagnosticsInScopeAsync().ConfigureAwait(false);
+
+
+                return CodeAction.Create(codeFixProvider.GetDiagnosticTitle(options),
+                    async ct =>
+                    {
+                        HashSet<Project> projectsToAddUnsafe = new();
+                        SolutionEditor solutionEditor = new SolutionEditor(fixAllContext.Solution);
+
+                        foreach (var diagnostic in diagnosticsInScope)
+                        {
+                            bool mayRequireAdditionalWork = diagnostic.Properties.TryGetValue(Option.MayRequireAdditionalWork, out string mayRequireAdditionalWorkString)
+                                && bool.TryParse(mayRequireAdditionalWorkString, out bool mayRequireAdditionalWorkValue)
+                                ? mayRequireAdditionalWorkValue
+                                : false;
+                            if (mayRequireAdditionalWork && !includeFixesWithAdditionalWork)
+                            {
+                                // Don't fix any diagnostics that require additional work if the "fix all" command wasn't triggered from a location
+                                // that was able to warn the user that additional work may be required.
+                                continue;
+                            }
+                            DocumentId documentId = solutionEditor.OriginalSolution.GetDocumentId(diagnostic.Location.SourceTree)!;
+                            DocumentEditor editor = await solutionEditor.GetDocumentEditorAsync(documentId, ct).ConfigureAwait(false);
+                            SyntaxNode root = await diagnostic.Location.SourceTree.GetRootAsync(ct).ConfigureAwait(false);
+
+                            SyntaxNode node = root.FindNode(diagnostic.Location.SourceSpan);
+
+                            var documentBasedFix = codeFixProvider.CreateFixForSelectedOptions(node, options);
+
+                            await documentBasedFix(editor, ct).ConfigureAwait(false);
+
+                            // Record this project as a project we need to allow unsafe blocks in.
+                            projectsToAddUnsafe.Add(solutionEditor.OriginalSolution.GetDocument(documentId).Project);
+                        }
+
+                        Solution solutionWithUpdatedSources = solutionEditor.GetChangedSolution();
+
+                        if (addUnsafe)
+                        {
+                            foreach (var project in projectsToAddUnsafe)
+                            {
+                                solutionWithUpdatedSources = AddUnsafe(solutionWithUpdatedSources, project);
+                            }
+                        }
+                        return solutionWithUpdatedSources;
+                    },
+                    equivalenceKey: fixAllContext.CodeActionEquivalenceKey);
+            }
+        }
+
+        private static Solution AddUnsafe(Solution solution, Project project)
+        {
+            return solution.WithProjectCompilationOptions(project.Id, ((CSharpCompilationOptions)project.CompilationOptions).WithAllowUnsafe(true));
+        }
+
+        protected static void MakeNodeParentsPartial(DocumentEditor editor, SyntaxNode syntax)
+        {
+            for (SyntaxNode? node = syntax.Parent; node is not null; node = node.Parent)
+            {
+                editor.ReplaceNode(node, (node, gen) => gen.WithModifiers(node, gen.GetModifiers(node).WithPartial(true)));
+            }
+        }
+
+        protected static SyntaxNode AddExplicitDefaultBoolMarshalling(SyntaxGenerator generator, IMethodSymbol methodSymbol, SyntaxNode generatedDeclaration, string unmanagedTypeMemberIdentifier)
+        {
+            foreach (IParameterSymbol parameter in methodSymbol.Parameters)
+            {
+                if (parameter.Type.SpecialType == SpecialType.System_Boolean
+                    && !parameter.GetAttributes().Any(attr => attr.AttributeClass?.ToDisplayString() == TypeNames.System_Runtime_InteropServices_MarshalAsAttribute))
+                {
+                    SyntaxNode generatedParameterSyntax = generator.GetParameters(generatedDeclaration)[parameter.Ordinal];
+                    generatedDeclaration = generator.ReplaceNode(generatedDeclaration, generatedParameterSyntax, generator.AddAttributes(generatedParameterSyntax,
+                                    GenerateMarshalAsUnmanagedTypeBoolAttribute(generator, unmanagedTypeMemberIdentifier)));
+                }
+            }
+
+            if (methodSymbol.ReturnType.SpecialType == SpecialType.System_Boolean
+                && !methodSymbol.GetReturnTypeAttributes().Any(attr => attr.AttributeClass?.ToDisplayString() == TypeNames.System_Runtime_InteropServices_MarshalAsAttribute))
+            {
+                generatedDeclaration = generator.AddReturnAttributes(generatedDeclaration,
+                    GenerateMarshalAsUnmanagedTypeBoolAttribute(generator, unmanagedTypeMemberIdentifier));
+            }
+
+            return generatedDeclaration;
+
+
+            static SyntaxNode GenerateMarshalAsUnmanagedTypeBoolAttribute(SyntaxGenerator generator, string unmanagedTypeMemberIdentifier)
+                 => generator.Attribute(TypeNames.System_Runtime_InteropServices_MarshalAsAttribute,
+                     generator.AttributeArgument(
+                         generator.MemberAccessExpression(
+                             generator.DottedName(TypeNames.System_Runtime_InteropServices_UnmanagedType),
+                             generator.IdentifierName(unmanagedTypeMemberIdentifier))));
+        }
+    }
+}
@@ -1,11 +1,9 @@
 // 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.Linq;
-using System.Text;
 using System.Threading.Tasks;
 using Microsoft.CodeAnalysis;
 using Microsoft.CodeAnalysis.CodeFixes;
index 14cbd22..60d6796 100644 (file)
@@ -23,249 +23,137 @@ using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics;
 namespace Microsoft.Interop.Analyzers
 {
     [ExportCodeFixProvider(LanguageNames.CSharp), Shared]
-    public sealed class ConvertToLibraryImportFixer : CodeFixProvider
+    public sealed class ConvertToLibraryImportFixer : ConvertToSourceGeneratedInteropFixer
     {
-        public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(Ids.ConvertToLibraryImport);
-
-        public override FixAllProvider GetFixAllProvider() => CustomFixAllProvider.Instance;
-
-        private const string ConvertToLibraryImportKey = "ConvertToLibraryImport,";
-        private static string AppendSuffix(string entryPoint, char? entryPointSuffix)
-            => entryPointSuffix.HasValue && entryPoint.LastOrDefault() == entryPointSuffix.Value
-                ? entryPoint
-                : entryPoint + entryPointSuffix;
-        private static string AddSuffixKey(string baseKey, char suffix) => $"{baseKey}{suffix},";
-        private static string AddUnsafeKey(string baseKey) => baseKey + "AddUnsafe,";
-        private static string AddMayRequireAdditionalWorkKey(string baseKey) => baseKey + $"{ConvertToLibraryImportAnalyzer.MayRequireAdditionalWork},";
-
-        private static readonly string[] s_preferredAttributeArgumentOrder =
-            {
-                nameof(DllImportAttribute.EntryPoint),
-                nameof(DllImportAttribute.BestFitMapping),
-                nameof(DllImportAttribute.CallingConvention),
-                nameof(DllImportAttribute.CharSet),
-                nameof(DllImportAttribute.ExactSpelling),
-                nameof(DllImportAttribute.PreserveSig),
-                nameof(DllImportAttribute.SetLastError),
-                nameof(StringMarshalling),
-                nameof(DllImportAttribute.ThrowOnUnmappableChar)
-            };
-
-        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
-        {
-            // Get the syntax root and semantic model
-            Document doc = context.Document;
-            SyntaxNode? root = await doc.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
-            if (root == null)
-                return;
-
-            // Get the syntax node tied to the diagnostic and check that it is a method declaration
-            if (root.FindNode(context.Span) is not MethodDeclarationSyntax methodSyntax)
-                return;
+        private const string CharSetOption = nameof(CharSetOption);
 
-            bool enableUnsafe = doc.Project.CompilationOptions is CSharpCompilationOptions { AllowUnsafe: false };
+        public const string SelectedSuffixOption = nameof(SelectedSuffixOption);
 
-            ICodeActionFactory codeActionFactory = enableUnsafe ? new AddUnsafeCodeActionFactory() : new DefaultCodeActionFactory();
-
-            foreach (Diagnostic diagnostic in context.Diagnostics)
-            {
-                bool mayRequireAdditionalWork = bool.TryParse(diagnostic.Properties[ConvertToLibraryImportAnalyzer.MayRequireAdditionalWork], out bool mayRequireAdditionalWorkValue)
-                    ? mayRequireAdditionalWorkValue
-                    : false;
-                // Register code fix
-                context.RegisterCodeFix(
-                    codeActionFactory.CreateConvertToLibraryImportCodeFix(doc, methodSyntax, mayRequireAdditionalWork),
-                    context.Diagnostics);
-                if (!bool.Parse(diagnostic.Properties[ConvertToLibraryImportAnalyzer.ExactSpelling]))
-                {
-                    CharSet charSet = (CharSet)Enum.Parse(typeof(CharSet), diagnostic.Properties[ConvertToLibraryImportAnalyzer.CharSet]!);
-                    // CharSet.Auto traditionally maps to either an A or W suffix
-                    // depending on the default CharSet of the platform.
-                    // We will offer both suffix options when CharSet.Auto is provided
-                    // to enable developers to pick which variant they mean (since they could explicitly decide they want one or the other)
-                    if (charSet is CharSet.None or CharSet.Ansi or CharSet.Auto)
-                    {
-                        context.RegisterCodeFix(
-                            codeActionFactory.CreateConvertToLibraryImportWithSuffixCodeFix(doc, methodSyntax, 'A', mayRequireAdditionalWork),
-                            context.Diagnostics);
-                    }
-                    if (charSet is CharSet.Unicode or CharSet.Auto)
-                    {
-                        context.RegisterCodeFix(
-                            codeActionFactory.CreateConvertToLibraryImportWithSuffixCodeFix(doc, methodSyntax, 'W', mayRequireAdditionalWork),
-                            context.Diagnostics);
-                    }
-                }
-            }
-        }
+        public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(Ids.ConvertToLibraryImport);
 
-        internal interface ICodeActionFactory
-        {
-            CodeAction CreateConvertToLibraryImportCodeFix(Document document, MethodDeclarationSyntax methodSyntax, bool mayRequireAdditionalWork);
-            CodeAction CreateConvertToLibraryImportWithSuffixCodeFix(Document document, MethodDeclarationSyntax methodSyntax, char suffix, bool mayRequireAdditionalWork);
-        }
+        protected override string BaseEquivalenceKey => "ConvertToLibraryImport";
 
-        private sealed class DefaultCodeActionFactory : ICodeActionFactory
+        protected override string GetDiagnosticTitle(ImmutableDictionary<string, Option> selectedOptions)
         {
-            public CodeAction CreateConvertToLibraryImportCodeFix(Document document, MethodDeclarationSyntax methodSyntax, bool mayRequireAdditionalWork)
+            bool allowUnsafe = selectedOptions.TryGetValue(Option.AllowUnsafe, out Option? allowUnsafeOption) && allowUnsafeOption is Option.Bool(true);
+            string? suffix = null;
+            bool hasSuffix = false;
+            if (selectedOptions.TryGetValue(SelectedSuffixOption, out Option? suffixOption) && suffixOption is Option.String(string suffixValue))
             {
-                return CodeAction.Create(
-                    SR.ConvertToLibraryImport,
-                    cancelToken => ConvertToLibraryImport(
-                        document,
-                        methodSyntax,
-                        mayRequireAdditionalWork,
-                        entryPointSuffix: null,
-                        cancelToken),
-                    equivalenceKey: mayRequireAdditionalWork ? AddMayRequireAdditionalWorkKey(ConvertToLibraryImportKey) : ConvertToLibraryImportKey);
+                hasSuffix = true;
+                suffix = suffixValue;
             }
-
-            public CodeAction CreateConvertToLibraryImportWithSuffixCodeFix(Document document, MethodDeclarationSyntax methodSyntax, char suffix, bool mayRequireAdditionalWork)
+            return (allowUnsafe, hasSuffix) switch
             {
-                return CodeAction.Create(
-                                SR.Format(SR.ConvertToLibraryImportWithSuffix, suffix),
-                                cancelToken => ConvertToLibraryImport(
-                                    document,
-                                    methodSyntax,
-                                    mayRequireAdditionalWork,
-                                    entryPointSuffix: suffix,
-                                    cancelToken),
-                                equivalenceKey: AddSuffixKey(mayRequireAdditionalWork ? AddMayRequireAdditionalWorkKey(ConvertToLibraryImportKey) : ConvertToLibraryImportKey, suffix));
-            }
+                (true, true) => SR.Format(SR.ConvertToLibraryImportWithSuffixAddUnsafe, suffix),
+                (true, false) => SR.ConvertToLibraryImportAddUnsafe,
+                (false, true) => SR.Format(SR.ConvertToLibraryImportWithSuffix, suffix),
+                (false, false) => SR.ConvertToLibraryImport
+            };
         }
 
-        private sealed class AddUnsafeCodeActionFactory : ICodeActionFactory
+        protected override ImmutableDictionary<string, Option> ParseOptionsFromDiagnostic(Diagnostic diagnostic)
         {
-            public CodeAction CreateConvertToLibraryImportCodeFix(Document document, MethodDeclarationSyntax methodSyntax, bool mayRequireAdditionalWork)
+            var optionsBuilder = ImmutableDictionary.CreateBuilder<string, Option>();
+            // Only add the "May require additional work" option if it is true. This simplifies our equivalence key and makes testing easier.
+            if (diagnostic.Properties.TryGetValue(ConvertToLibraryImportAnalyzer.MayRequireAdditionalWork, out string? mayRequireAdditionalWork) && bool.Parse(mayRequireAdditionalWork))
             {
-                return CodeAction.Create(
-                    SR.ConvertToLibraryImportAddUnsafe,
-                    async cancelToken =>
-                    {
-                        Solution solutionWithUnsafe = AddUnsafe(document.Project.Solution, document.Project);
-                        SolutionEditor editor = new SolutionEditor(solutionWithUnsafe);
-
-                        await ConvertToLibraryImport(
-                            await editor.GetDocumentEditorAsync(document.Id, cancelToken).ConfigureAwait(false),
-                            methodSyntax,
-                            mayRequireAdditionalWork,
-                            entryPointSuffix: null,
-                            cancelToken).ConfigureAwait(false);
-                        return editor.GetChangedSolution();
-                    },
-                    equivalenceKey: AddUnsafeKey(mayRequireAdditionalWork ? AddMayRequireAdditionalWorkKey(ConvertToLibraryImportKey) : ConvertToLibraryImportKey));
+                optionsBuilder.Add(Option.MayRequireAdditionalWork, new Option.Bool(true));
             }
-
-            public CodeAction CreateConvertToLibraryImportWithSuffixCodeFix(Document document, MethodDeclarationSyntax methodSyntax, char suffix, bool mayRequireAdditionalWork)
+            if (!bool.Parse(diagnostic.Properties[ConvertToLibraryImportAnalyzer.ExactSpelling]))
             {
-                return CodeAction.Create(
-                    SR.Format(SR.ConvertToLibraryImportWithSuffixAddUnsafe, suffix),
-                    async cancelToken =>
-                    {
-                        Solution solutionWithUnsafe = AddUnsafe(document.Project.Solution, document.Project);
-                        SolutionEditor editor = new SolutionEditor(solutionWithUnsafe);
-
-                        await ConvertToLibraryImport(
-                            await editor.GetDocumentEditorAsync(document.Id, cancelToken).ConfigureAwait(false),
-                            methodSyntax,
-                            mayRequireAdditionalWork,
-                            entryPointSuffix: suffix,
-                            cancelToken).ConfigureAwait(false);
-                        return editor.GetChangedSolution();
-                    },
-                    equivalenceKey: AddUnsafeKey(AddSuffixKey(mayRequireAdditionalWork ? AddMayRequireAdditionalWorkKey(ConvertToLibraryImportKey) : ConvertToLibraryImportKey, suffix)));
+                optionsBuilder.Add(CharSetOption, new Option.String(diagnostic.Properties[ConvertToLibraryImportAnalyzer.CharSet]));
             }
+            return optionsBuilder.ToImmutable();
         }
 
-        private sealed class CustomFixAllProvider : FixAllProvider
+        protected override IEnumerable<ConvertToSourceGeneratedInteropFix> CreateAllFixesForDiagnosticOptions(SyntaxNode node, ImmutableDictionary<string, Option> options)
         {
-            public static readonly CustomFixAllProvider Instance = new();
-            public override async Task<CodeAction?> GetFixAsync(FixAllContext fixAllContext)
-            {
-                bool addUnsafe = fixAllContext.CodeActionEquivalenceKey.Contains(",AddUnsafe,");
-                bool includeFixesWithAdditionalWork = fixAllContext.CodeActionEquivalenceKey.Contains($",{ConvertToLibraryImportAnalyzer.MayRequireAdditionalWork},");
-                ImmutableArray<Diagnostic> diagnosticsInScope = await fixAllContext.GetDiagnosticsInScopeAsync().ConfigureAwait(false);
+            bool warnForAdditionalWork = options.TryGetValue(Option.MayRequireAdditionalWork, out Option mayRequireAdditionalWork) && mayRequireAdditionalWork is Option.Bool(true);
 
-                return CodeAction.Create(addUnsafe ? SR.ConvertToLibraryImportAddUnsafe : SR.ConvertToLibraryImport,
-                    async ct =>
-                    {
-                        HashSet<Project> projectsToAddUnsafe = new();
-                        SolutionEditor solutionEditor = new SolutionEditor(fixAllContext.Solution);
+            CharSet? charSet = options.TryGetValue(CharSetOption, out Option charSetOption) && charSetOption is Option.String(string charSetString) && Enum.TryParse<CharSet>(charSetString, out CharSet result) ? result : null;
 
-                        foreach (var diagnostic in diagnosticsInScope)
-                        {
-                            bool mayRequireAdditionalWork = bool.TryParse(diagnostic.Properties[ConvertToLibraryImportAnalyzer.MayRequireAdditionalWork], out bool mayRequireAdditionalWorkValue)
-                                ? mayRequireAdditionalWorkValue
-                                : false;
-                            if (mayRequireAdditionalWork && !includeFixesWithAdditionalWork)
-                            {
-                                // Don't fix any diagnostics that require additional work if the "fix all" command wasn't triggered from a location
-                                // that was able to warn the user that additional work may be required.
-                                continue;
-                            }
-                            DocumentId documentId = solutionEditor.OriginalSolution.GetDocumentId(diagnostic.Location.SourceTree)!;
-                            DocumentEditor editor = await solutionEditor.GetDocumentEditorAsync(documentId, ct).ConfigureAwait(false);
-                            SyntaxNode root = await diagnostic.Location.SourceTree.GetRootAsync(ct).ConfigureAwait(false);
-
-                            // Get the syntax node tied to the diagnostic and check that it is a method declaration
-                            if (root.FindNode(diagnostic.Location.SourceSpan) is not MethodDeclarationSyntax methodSyntax)
-                                continue;
-
-                            await ConvertToLibraryImport(editor, methodSyntax, mayRequireAdditionalWork, GetSuffixFromEquivalenceKey(fixAllContext.CodeActionEquivalenceKey), ct).ConfigureAwait(false);
-
-                            // Record this project as a project we need to allow unsafe blocks in.
-                            projectsToAddUnsafe.Add(solutionEditor.OriginalSolution.GetDocument(documentId).Project);
-                        }
-
-                        Solution solutionWithUpdatedSources = solutionEditor.GetChangedSolution();
-
-                        if (addUnsafe)
-                        {
-                            foreach (var project in projectsToAddUnsafe)
-                            {
-                                solutionWithUpdatedSources = AddUnsafe(solutionWithUpdatedSources, project);
-                            }
-                        }
-                        return solutionWithUpdatedSources;
-                    },
-                    equivalenceKey: fixAllContext.CodeActionEquivalenceKey);
-            }
+            // We don't want the CharSet option contributing to the "selected options" set for the fix, so we remove it here.
+            var selectedOptions = options.Remove(CharSetOption);
 
+            yield return new ConvertToSourceGeneratedInteropFix(
+                (editor, ct) =>
+                    ConvertToLibraryImport(
+                        editor,
+                        node,
+                        warnForAdditionalWork,
+                        null,
+                        ct),
+                selectedOptions);
 
-            private static char? GetSuffixFromEquivalenceKey(string equivalenceKey)
+            if (charSet is not null)
             {
-                if (equivalenceKey.Contains(",A,"))
+
+                // CharSet.Auto traditionally maps to either an A or W suffix
+                // depending on the default CharSet of the platform.
+                // We will offer both suffix options when CharSet.Auto is provided
+                // to enable developers to pick which variant they mean (since they could explicitly decide they want one or the other)
+                if (charSet is CharSet.None or CharSet.Ansi or CharSet.Auto)
                 {
-                    return 'A';
+                    yield return new ConvertToSourceGeneratedInteropFix(
+                        (editor, ct) =>
+                            ConvertToLibraryImport(
+                                editor,
+                                node,
+                                warnForAdditionalWork,
+                                'A',
+                                ct),
+                        selectedOptions.Add(SelectedSuffixOption, new Option.String("A")));
                 }
-                if (equivalenceKey.Contains(",W,"))
+                if (charSet is CharSet.Unicode or CharSet.Auto)
                 {
-                    return 'W';
+                    yield return new ConvertToSourceGeneratedInteropFix(
+                        (editor, ct) =>
+                            ConvertToLibraryImport(
+                                editor,
+                                node,
+                                warnForAdditionalWork,
+                                'W',
+                                ct),
+                        selectedOptions.Add(SelectedSuffixOption, new Option.String("W")));
                 }
-                return null;
             }
         }
 
-        private static Solution AddUnsafe(Solution solution, Project project)
+        protected override Func<DocumentEditor, CancellationToken, Task> CreateFixForSelectedOptions(SyntaxNode node, ImmutableDictionary<string, Option> selectedOptions)
         {
-            return solution.WithProjectCompilationOptions(project.Id, ((CSharpCompilationOptions)project.CompilationOptions).WithAllowUnsafe(true));
+            bool warnForAdditionalWork = selectedOptions.TryGetValue(Option.MayRequireAdditionalWork, out Option mayRequireAdditionalWork) && mayRequireAdditionalWork is Option.Bool(true);
+            char? suffix = selectedOptions.TryGetValue(SelectedSuffixOption, out Option selectedSuffixOption) && selectedSuffixOption is Option.String(string selectedSuffix) ? selectedSuffix[0] : null;
+            return (editor, ct) =>
+                ConvertToLibraryImport(
+                    editor,
+                    node,
+                    warnForAdditionalWork,
+                    suffix,
+                    ct);
         }
 
-        private static async Task<Document> ConvertToLibraryImport(
-            Document doc,
-            MethodDeclarationSyntax methodSyntax,
-            bool warnForAdditionalWork,
-            char? entryPointSuffix,
-            CancellationToken cancellationToken)
-        {
-            DocumentEditor editor = await DocumentEditor.CreateAsync(doc, cancellationToken).ConfigureAwait(false);
-            await ConvertToLibraryImport(editor, methodSyntax, warnForAdditionalWork, entryPointSuffix, cancellationToken).ConfigureAwait(false);
-            return editor.GetChangedDocument();
-        }
+        private static string AppendSuffix(string entryPoint, char? entryPointSuffix)
+            => entryPointSuffix.HasValue && entryPoint.LastOrDefault() == entryPointSuffix.Value
+                ? entryPoint
+                : entryPoint + entryPointSuffix;
+
+        private static readonly string[] s_preferredAttributeArgumentOrder =
+            {
+                nameof(DllImportAttribute.EntryPoint),
+                nameof(DllImportAttribute.BestFitMapping),
+                nameof(DllImportAttribute.CallingConvention),
+                nameof(DllImportAttribute.CharSet),
+                nameof(DllImportAttribute.ExactSpelling),
+                nameof(DllImportAttribute.PreserveSig),
+                nameof(DllImportAttribute.SetLastError),
+                nameof(StringMarshalling),
+                nameof(DllImportAttribute.ThrowOnUnmappableChar)
+            };
 
         private static async Task ConvertToLibraryImport(
             DocumentEditor editor,
-            MethodDeclarationSyntax methodSyntax,
+            SyntaxNode methodSyntax,
             bool warnForAdditionalWork,
             char? entryPointSuffix,
             CancellationToken cancellationToken)
@@ -296,11 +184,11 @@ namespace Microsoft.Interop.Analyzers
             // Replace the original method with the updated one
             editor.ReplaceNode(methodSyntax, generatedDeclaration);
 
-            MakeEnclosingTypesPartial(editor, methodSyntax);
+            MakeNodeParentsPartial(editor, methodSyntax);
         }
 
         private static async Task<SyntaxNode> ConvertMethodDeclarationToLibraryImport(
-            MethodDeclarationSyntax methodSyntax,
+            SyntaxNode methodSyntax,
             DocumentEditor editor,
             SyntaxGenerator generator,
             IMethodSymbol methodSymbol,
@@ -308,12 +196,12 @@ namespace Microsoft.Interop.Analyzers
             char? entryPointSuffix,
             CancellationToken cancellationToken)
         {
-            INamedTypeSymbol? dllImportAttrType = editor.SemanticModel.Compilation.GetTypeByMetadataName(typeof(DllImportAttribute).FullName);
+            INamedTypeSymbol? dllImportAttrType = editor.SemanticModel.Compilation.GetBestTypeByMetadataName(typeof(DllImportAttribute).FullName);
             if (dllImportAttrType == null)
                 return methodSyntax;
 
             // We wouldn't have offered this code fix if the LibraryImport type isn't available, so we can be sure it isn't null here.
-            INamedTypeSymbol libraryImportAttrType = editor.SemanticModel.Compilation.GetTypeByMetadataName(TypeNames.LibraryImportAttribute)!;
+            INamedTypeSymbol libraryImportAttrType = editor.SemanticModel.Compilation.GetBestTypeByMetadataName(TypeNames.LibraryImportAttribute)!;
 
             // Make sure the method has the DllImportAttribute
             if (!TryGetAttribute(methodSymbol, dllImportAttrType, out AttributeData? dllImportAttr))
@@ -369,43 +257,11 @@ namespace Microsoft.Interop.Analyzers
                     .WithIsExtern(false)
                     .WithPartial(true));
 
-            foreach (IParameterSymbol parameter in methodSymbol.Parameters)
-            {
-                if (parameter.Type.SpecialType == SpecialType.System_Boolean
-                    && !parameter.GetAttributes().Any(attr => attr.AttributeClass?.ToDisplayString() == TypeNames.System_Runtime_InteropServices_MarshalAsAttribute))
-                {
-                    MethodDeclarationSyntax generatedDeclarationSyntax = (MethodDeclarationSyntax)generatedDeclaration;
-                    ParameterSyntax generatedParameterSyntax = generatedDeclarationSyntax.ParameterList.Parameters[parameter.Ordinal];
-                    generatedDeclaration = generator.ReplaceNode(generatedDeclaration, generatedParameterSyntax, generator.AddAttributes(generatedParameterSyntax,
-                                    GenerateMarshalAsUnmanagedTypeBoolAttribute(generator)));
-                }
-            }
-
-            if (methodSymbol.ReturnType.SpecialType == SpecialType.System_Boolean
-                && !methodSymbol.GetReturnTypeAttributes().Any(attr => attr.AttributeClass?.ToDisplayString() == TypeNames.System_Runtime_InteropServices_MarshalAsAttribute))
-            {
-                generatedDeclaration = generator.AddReturnAttributes(generatedDeclaration,
-                    GenerateMarshalAsUnmanagedTypeBoolAttribute(generator));
-            }
+            generatedDeclaration = AddExplicitDefaultBoolMarshalling(generator, methodSymbol, generatedDeclaration, "Bool");
 
             return generatedDeclaration;
         }
 
-        private static SyntaxNode GenerateMarshalAsUnmanagedTypeBoolAttribute(SyntaxGenerator generator)
-         => generator.Attribute(TypeNames.System_Runtime_InteropServices_MarshalAsAttribute,
-             generator.AttributeArgument(
-                 generator.MemberAccessExpression(
-                     generator.DottedName(TypeNames.System_Runtime_InteropServices_UnmanagedType),
-                     generator.IdentifierName("Bool"))));
-
-        private static void MakeEnclosingTypesPartial(DocumentEditor editor, MethodDeclarationSyntax method)
-        {
-            for (TypeDeclarationSyntax? typeDecl = method.FirstAncestorOrSelf<TypeDeclarationSyntax>(); typeDecl is not null; typeDecl = typeDecl.Parent.FirstAncestorOrSelf<TypeDeclarationSyntax>())
-            {
-                editor.ReplaceNode(typeDecl, (node, generator) => generator.WithModifiers(node, generator.GetModifiers(node).WithPartial(true)));
-            }
-        }
-
         private static async Task<bool> TransformCallersOfNoPreserveSigMethod(DocumentEditor editor, IMethodSymbol methodSymbol, CancellationToken cancellationToken)
         {
             Document? document = editor.OriginalDocument;
@@ -539,7 +395,7 @@ namespace Microsoft.Interop.Analyzers
                 return generator.InvocationExpression(
                             generator.MemberAccessExpression(
                                 generator.NameExpression(
-                                    editor.SemanticModel.Compilation.GetTypeByMetadataName(
+                                    editor.SemanticModel.Compilation.GetBestTypeByMetadataName(
                                         TypeNames.System_Runtime_InteropServices_Marshal)),
                                 "ThrowExceptionForHR"),
                             node);
@@ -710,7 +566,7 @@ namespace Microsoft.Interop.Analyzers
             CallingConvention callingConvention,
             out SyntaxNode? unmanagedCallConvAttribute)
         {
-            if (editor.SemanticModel.Compilation.GetTypeByMetadataName(TypeNames.UnmanagedCallConvAttribute) is null)
+            if (editor.SemanticModel.Compilation.GetBestTypeByMetadataName(TypeNames.UnmanagedCallConvAttribute) is null)
             {
                 unmanagedCallConvAttribute = null;
                 return false;
@@ -727,13 +583,13 @@ namespace Microsoft.Interop.Analyzers
             ITypeSymbol? callingConventionType = callingConvention switch
             {
                 CallingConvention.Cdecl => editor.SemanticModel.Compilation.ObjectType.ContainingAssembly.
-                GetTypeByMetadataName($"System.Runtime.CompilerServices.CallConvCdecl"),
+                    GetTypeByMetadataName($"System.Runtime.CompilerServices.CallConvCdecl"),
                 CallingConvention.StdCall => editor.SemanticModel.Compilation.ObjectType.ContainingAssembly.
-                GetTypeByMetadataName($"System.Runtime.CompilerServices.CallConvStdcall"),
+                    GetTypeByMetadataName($"System.Runtime.CompilerServices.CallConvStdcall"),
                 CallingConvention.ThisCall => editor.SemanticModel.Compilation.ObjectType.ContainingAssembly.
-                GetTypeByMetadataName($"System.Runtime.CompilerServices.CallConvThiscall"),
+                    GetTypeByMetadataName($"System.Runtime.CompilerServices.CallConvThiscall"),
                 CallingConvention.FastCall => editor.SemanticModel.Compilation.ObjectType.ContainingAssembly.
-                GetTypeByMetadataName($"System.Runtime.CompilerServices.CallConvFastcall"),
+                    GetTypeByMetadataName($"System.Runtime.CompilerServices.CallConvFastcall"),
                 _ => null
             };
 
@@ -749,7 +605,7 @@ namespace Microsoft.Interop.Analyzers
             unmanagedCallConvAttribute = generator.Attribute(TypeNames.UnmanagedCallConvAttribute,
                 generator.AttributeArgument("CallConvs",
                     generator.ArrayCreationExpression(
-                        generator.TypeExpression(editor.SemanticModel.Compilation.GetTypeByMetadataName(TypeNames.System_Type)),
+                        generator.TypeExpression(editor.SemanticModel.Compilation.GetBestTypeByMetadataName(TypeNames.System_Type)),
                         new[] { generator.TypeOfExpression(generator.TypeExpression(callingConventionType)) })));
 
             return true;
index 26ac96b..621caea 100644 (file)
 
   <ItemGroup>
     <Compile Include="$(CommonPath)Roslyn\GetBestTypeByMetadataName.cs" Link="Common\Roslyn\GetBestTypeByMetadataName.cs" />
-
-    <Compile Include="$(CoreLibSharedDir)System\Collections\Generic\ValueListBuilder.cs" Link="Production\ValueListBuilder.cs" />
-    <Compile Include="$(CoreLibSharedDir)System\Collections\Generic\ValueListBuilder.Pop.cs" Link="Production\ValueListBuilder.Pop.cs" />
     <Compile Include="..\Common\DefaultMarshallingInfoParser.cs" Link="Common\DefaultMarshallingInfoParser.cs" />
+    <Compile Include="..\Common\OperationExtensions.cs" Link="Common\OperationExtensions.cs" />
+    <Compile Include="..\Common\ConvertToSourceGeneratedInteropFixer.cs" Link="Common\ConvertToSourceGeneratedInteropFixer.cs" />
+    <Compile Include="..\Common\FixAllContextExtensions.cs" Link="Common\FixAllContextExtensions.cs" />
   </ItemGroup>
 
 </Project>
index de83283..75c56f3 100644 (file)
@@ -36,6 +36,7 @@ namespace Microsoft.Interop
         public const string UnmanagedCallersOnlyAttribute = "System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute";
 
         public const string System_Runtime_InteropServices_ComImportAttribute = "System.Runtime.InteropServices.ComImportAttribute";
+        public const string System_Runtime_InteropServices_ComVisibleAttribute = "System.Runtime.InteropServices.ComVisibleAttribute";
 
         public const string VirtualMethodIndexAttribute = "System.Runtime.InteropServices.Marshalling.VirtualMethodIndexAttribute";
         public const string VirtualMethodIndexAttribute_ShortName = "VirtualMethodIndexAttribute";
@@ -116,7 +117,7 @@ namespace Microsoft.Interop
 
         public const string InterfaceTypeAttribute = "System.Runtime.InteropServices.InterfaceTypeAttribute";
 
-        public const string ComInterfaceTypeAttribute = "System.Runtime.InteropServices.ComInterfaceType";
+        public const string ComInterfaceType = "System.Runtime.InteropServices.ComInterfaceType";
 
         public const string System_Runtime_InteropServices_GuidAttribute = "System.Runtime.InteropServices.GuidAttribute";
 
@@ -149,5 +150,7 @@ namespace Microsoft.Interop
         public const string System_Runtime_InteropServices_Marshalling_SafeHandleMarshaller_Metadata = "System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller`1";
 
         public const string System_Runtime_InteropServices_Marshalling_ComInterfaceMarshaller_Metadata = "System.Runtime.InteropServices.Marshalling.ComInterfaceMarshaller`1";
+
+        public const string System_Runtime_InteropServices_Marshalling_ComObject = "System.Runtime.InteropServices.Marshalling.ComObject";
     }
 }
diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/AddGeneratedComClassTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/AddGeneratedComClassTests.cs
new file mode 100644 (file)
index 0000000..111ff15
--- /dev/null
@@ -0,0 +1,125 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Threading.Tasks;
+using Xunit;
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpCodeFixVerifier<
+       Microsoft.Interop.Analyzers.AddGeneratedComClassAnalyzer,
+       Microsoft.Interop.Analyzers.AddGeneratedComClassFixer>;
+
+namespace ComInterfaceGenerator.Unit.Tests
+{
+    [ActiveIssue("https://github.com/dotnet/runtime/issues/60650", TestRuntimes.Mono)]
+    public class AddGeneratedComClassTests
+    {
+        [Fact]
+        public async Task TypeThatImplementsGeneratedComInterfaceType_ReportsDiagnostic()
+        {
+            string source = """
+               using System.Runtime.InteropServices;
+               using System.Runtime.InteropServices.Marshalling;
+
+               [GeneratedComInterface]
+               [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+               public partial interface I
+               {
+               }
+
+               class [|C|] : I
+               {
+               }
+               """;
+
+            string fixedSource = """
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+                
+                [GeneratedComInterface]
+                [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+                public partial interface I
+                {
+                }
+
+                [GeneratedComClass]
+                partial class C : I
+                {
+                }
+                """;
+
+            await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+        }
+
+        [Fact]
+        public async Task TypeThatDoesNotImplementGeneratedComInterfaceType_DoesNotReportDiagnostic()
+        {
+            string source = """
+                using System.Runtime.InteropServices;
+
+                [ComImport]
+                [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+                public interface I
+                {
+                }
+
+                public interface NonComInterface
+                {
+                }
+
+                class C : I
+                {
+                }
+
+                class D : NonComInterface
+                {
+                }
+                """;
+
+            await VerifyCS.VerifyCodeFixAsync(source, source);
+        }
+
+        [Fact]
+        public async Task TypeThatImplementsGeneratedComInterfaceTypeTranstively_ReportsDiagnostic()
+        {
+            string source = """
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+
+                [GeneratedComInterface]
+                [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+                public partial interface I
+                {
+                }
+
+                public interface J : I
+                {
+                }
+
+                class [|C|] : J
+                {
+                }
+                """;
+
+            string fixedSource = """
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+    
+                [GeneratedComInterface]
+                [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+                public partial interface I
+                {
+                }
+                
+                public interface J : I
+                {
+                }
+
+                [GeneratedComClass]
+                partial class C : J
+                {
+                }
+                """;
+
+            await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComHostingDoesNotSupportGeneratedComInterfaceTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComHostingDoesNotSupportGeneratedComInterfaceTests.cs
new file mode 100644 (file)
index 0000000..4256d36
--- /dev/null
@@ -0,0 +1,135 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Threading.Tasks;
+using Xunit;
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpAnalyzerVerifier<
+       Microsoft.Interop.Analyzers.ComHostingDoesNotSupportGeneratedComInterfaceAnalyzer>;
+
+namespace ComInterfaceGenerator.Unit.Tests
+{
+    [ActiveIssue("https://github.com/dotnet/runtime/issues/60650", TestRuntimes.Mono)]
+    public class ComHostingDoesNotSupportGeneratedComInterfaceTests
+    {
+        [InlineData(true)]
+        [InlineData(false)]
+        [Theory]
+        public async Task ComVisibleType_ComImportInterfacesOnly_DoesNotReportDiagnostic(bool enableComHosting)
+        {
+            string source = """
+                using System.Runtime.InteropServices;
+
+                [ComVisible(true)]
+                [Guid("12D46FF1-E21A-45E4-8407-0573B30962FE")]
+                [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+                public interface I
+                {
+                }
+
+                [ComVisible(true)]
+                public class C : I
+                {
+                }
+                                
+                """;
+
+            await VerifyAnalyzerAsync(source, enableComHosting);
+        }
+
+        [Fact]
+        public async Task ComVisibleType_GeneratedComInterface_NoHosting_DoesNotReportDiagnostic()
+        {
+            string source = """
+               using System.Runtime.InteropServices;
+               using System.Runtime.InteropServices.Marshalling;
+
+               [GeneratedComInterface]
+               [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public interface I
+               {
+               }
+
+               [ComVisible(true)]
+               public class C : I
+               {
+               }
+       
+               """;
+
+            await VerifyAnalyzerAsync(source, enableComHosting: false);
+        }
+
+        [Fact]
+        public async Task ComVisibleType_GeneratedComInterface_EnabledHosting_ReportsDiagnostic()
+        {
+            string source = """
+               using System.Runtime.InteropServices;
+               using System.Runtime.InteropServices.Marshalling;
+
+               [GeneratedComInterface]
+               [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public partial interface I
+               {
+               }
+
+               [ComVisible(true)]
+               public class [|C|] : I
+               {
+               }
+       
+               """;
+
+            await VerifyAnalyzerAsync(source, enableComHosting: true);
+        }
+
+        [Fact]
+        public async Task ComVisibleType_GeneratedComInterface_TransitiveInterface_EnabledHosting_ReportsDiagnostic()
+        {
+            string source = """
+               using System.Runtime.InteropServices;
+               using System.Runtime.InteropServices.Marshalling;
+
+               [GeneratedComInterface]
+               [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public partial interface I
+               {
+               }
+
+               public interface J : I
+               {
+               }
+
+               [ComVisible(true)]
+               public class [|C|] : I
+               {
+               }
+       
+               """;
+
+            await VerifyAnalyzerAsync(source, enableComHosting: true);
+        }
+
+        private static Task VerifyAnalyzerAsync(string source, bool enableComHosting)
+        {
+            var test = new VerifyCS.Test
+            {
+                TestState =
+                {
+                    Sources = { source },
+                    AnalyzerConfigFiles =
+                    {
+                        ("/.editorconfig", $"""
+                                            is_global = true
+                                            build_property.EnableComHosting = {enableComHosting}
+                                            """)
+                    }
+                }
+            };
+
+            return test.RunAsync();
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ConvertToGeneratedComInterfaceTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ConvertToGeneratedComInterfaceTests.cs
new file mode 100644 (file)
index 0000000..a48ca54
--- /dev/null
@@ -0,0 +1,329 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Threading.Tasks;
+using Xunit;
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpCodeFixVerifier<
+       Microsoft.Interop.Analyzers.ConvertComImportToGeneratedComInterfaceAnalyzer,
+          Microsoft.Interop.Analyzers.ConvertComImportToGeneratedComInterfaceFixer>;
+
+namespace ComInterfaceGenerator.Unit.Tests
+{
+    [ActiveIssue("https://github.com/dotnet/runtime/issues/60650", TestRuntimes.Mono)]
+    public class ConvertToGeneratedComInterfaceTests
+    {
+        [Fact]
+        public async Task Empty_ReportsDiagnostic()
+        {
+            string source = """
+                using System.Runtime.InteropServices;
+
+                [ComImport]
+                [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+                [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+                public interface [|I|]
+                {
+                }
+                """;
+
+            string fixedSource = """
+               using System.Runtime.InteropServices;
+               using System.Runtime.InteropServices.Marshalling;
+
+               [GeneratedComInterface]
+               [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public partial interface I
+               {
+               }
+               """;
+
+            await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+        }
+
+        [Fact]
+        public async Task PrimitiveArgument_ReportsDiagnostic()
+        {
+            string source = """
+               using System.Runtime.InteropServices;
+
+               [ComImport]
+               [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public interface [|I|]
+               {
+                    void Foo(int a);
+               }
+               """;
+
+            string fixedSource = """
+               using System.Runtime.InteropServices;
+               using System.Runtime.InteropServices.Marshalling;
+
+               [GeneratedComInterface]
+               [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public partial interface I
+               {
+                    void Foo(int a);
+               }
+               """;
+
+            await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+        }
+
+        [Fact]
+        public async Task Bool_MarshalsAsVariantBool()
+        {
+            string source = """
+               using System.Runtime.InteropServices;
+
+               [ComImport]
+               [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public interface [|I|]
+               {
+                    bool Foo(bool a);
+               }
+               """;
+
+            string fixedSource = """
+               using System.Runtime.InteropServices;
+               using System.Runtime.InteropServices.Marshalling;
+
+               [GeneratedComInterface]
+               [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public partial interface I
+               {
+                   [return: MarshalAs(UnmanagedType.VariantBool)]
+                   bool Foo([MarshalAs(UnmanagedType.VariantBool)] bool a);
+               }
+               """;
+
+            await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+        }
+
+        [Fact]
+        public async Task String_AddsStringMarshallingBStr()
+        {
+            string source = """
+                using System.Runtime.InteropServices;
+
+                [ComImport]
+                [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+                [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+                public interface [|I|]
+                {
+                    string Foo(string a);
+                }
+                """;
+
+            string fixedSource = """
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+
+                [GeneratedComInterface(StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(BStrStringMarshaller))]
+                [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+                [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+                public partial interface I
+                {
+                    string Foo(string a);
+                }
+                """;
+
+            await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+        }
+
+        [Fact]
+        public async Task Array_DoesNotReportDiagnostic()
+        {
+            // The default behavior in ComImport for arrays is to marshal as a SAFEARRAY. We don't support SAFEARRAY's, so we don't want to offer a fix here.
+            string source = """
+               using System.Runtime.InteropServices;
+
+               [ComImport]
+               [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public interface I
+               {
+                   void Foo(int[] a);
+               }
+               """;
+
+            await VerifyCS.VerifyCodeFixAsync(source, source);
+        }
+
+        [Fact]
+        public async Task Delegate_DoesNotReportDiagnostic()
+        {
+            // The default behavior in ComImport for delegates is to marshal as a COM object with an undefined interface. We don't support that interface, so we don't offer a fix here.
+            string source = """
+               using System;
+               using System.Runtime.InteropServices;
+
+               [ComImport]
+               [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public interface I
+               {
+                   void Foo(Action a);
+               }
+               """;
+
+            await VerifyCS.VerifyCodeFixAsync(source, source);
+        }
+
+        [Fact]
+        public async Task Object_DoesNotReportDiagnostic()
+        {
+            // The default behavior in ComImport for Object is to marshal as a VARIANT. We don't support VARIANTs, so we don't offer a fix here.
+            string source = """
+               using System.Runtime.InteropServices;
+
+               [ComImport]
+               [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public interface I
+               {
+                   object Foo(object o);
+               }
+               """;
+
+            await VerifyCS.VerifyCodeFixAsync(source, source);
+        }
+
+        [Fact]
+        public async Task SystemArray_DoesNotReportDiagnostic()
+        {
+            // The default behavior in ComImport for System.Array is to marshal as a COM interface. We don't support that interface, so we don't offer a fix here.
+            string source = """
+               using System;
+               using System.Runtime.InteropServices;
+
+               [ComImport]
+               [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public interface I
+               {
+                   Array Foo(Array o);
+               }
+               """;
+
+            await VerifyCS.VerifyCodeFixAsync(source, source);
+        }
+
+        [Fact]
+        public async Task Delegate_WithMarshalAs_ReportsDiagnostic()
+        {
+            string source = """
+               using System;
+               using System.Runtime.InteropServices;
+
+               [ComImport]
+               [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public interface [|I|]
+               {
+                   void Foo([MarshalAs(UnmanagedType.FunctionPtr)] Action a);
+               }
+               """;
+
+            string fixedSource = """
+                using System;
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+
+                [GeneratedComInterface]
+                [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+                [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+                public partial interface I
+                {
+                    void Foo([MarshalAs(UnmanagedType.FunctionPtr)] Action a);
+                }
+                """;
+
+            await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+        }
+
+        [Fact]
+        public async Task Array_WithMarshalAs_ReportsDiagnostic()
+        {
+            string source = """
+               using System.Runtime.InteropServices;
+
+               [ComImport]
+               [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public interface [|I|]
+               {
+                   void Foo([MarshalAs(UnmanagedType.LPArray, SizeConst = 10)] int[] a);
+               }
+               """;
+
+            string fixedSource = """
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+
+                [GeneratedComInterface]
+                [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+                [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+                public partial interface I
+                {
+                    void Foo([MarshalAs(UnmanagedType.LPArray, SizeConst = 10)] int[] a);
+                }
+                """;
+
+            await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+        }
+
+        [Fact]
+        public async Task InterfaceInheritance_RemovesShadowingMembers()
+        {
+            string source = """
+               using System.Runtime.InteropServices;
+
+               [ComImport]
+               [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public interface [|I|]
+               {
+                   void Foo(int a);
+               }
+
+               [ComImport]
+               [Guid("F59AB2FE-523D-4B28-911C-21363808C51E")]
+               [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+               public interface [|J|] : I
+               {
+                   new void Foo(int a);
+
+                   void Bar(short a);
+               }
+               """;
+
+            string fixedSource = """
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+
+                [GeneratedComInterface]
+                [Guid("5DA39CDF-DCAD-447A-836E-EA80DB34D81B")]
+                [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+                public partial interface I
+                {
+                    void Foo(int a);
+                }
+
+                [GeneratedComInterface]
+                [Guid("F59AB2FE-523D-4B28-911C-21363808C51E")]
+                [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+                public partial interface J : I
+                {
+                    void Bar(short a);
+                }
+                """;
+
+            await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
+        }
+    }
+}
index 1258854..32d2801 100644 (file)
@@ -214,7 +214,7 @@ namespace ComInterfaceGenerator.Unit.Tests
                     _usings + snippet,
                     VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
                         .WithLocation(0)
-                        .WithArguments(TypeNames.ComInterfaceTypeAttribute + "." + nameof(ComInterfaceType.InterfaceIsIDispatch)));
+                        .WithArguments(TypeNames.ComInterfaceType + "." + nameof(ComInterfaceType.InterfaceIsIDispatch)));
             }
 
             [Fact]
@@ -254,7 +254,7 @@ namespace ComInterfaceGenerator.Unit.Tests
                     _usings + snippet,
                     VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
                         .WithLocation(0)
-                        .WithArguments(TypeNames.ComInterfaceTypeAttribute + "." + nameof(ComInterfaceType.InterfaceIsIInspectable)));
+                        .WithArguments(TypeNames.ComInterfaceType + "." + nameof(ComInterfaceType.InterfaceIsIInspectable)));
             }
 
             [Fact]
@@ -294,7 +294,7 @@ namespace ComInterfaceGenerator.Unit.Tests
                     _usings + snippet,
                     VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
                         .WithLocation(0)
-                        .WithArguments(TypeNames.ComInterfaceTypeAttribute + "." + nameof(ComInterfaceType.InterfaceIsDual)));
+                        .WithArguments(TypeNames.ComInterfaceType + "." + nameof(ComInterfaceType.InterfaceIsDual)));
             }
 
             [Fact]
@@ -376,7 +376,7 @@ namespace ComInterfaceGenerator.Unit.Tests
                     _usings + snippet,
                     VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
                         .WithLocation(0)
-                        .WithArguments(TypeNames.ComInterfaceTypeAttribute + "." + nameof(ComInterfaceType.InterfaceIsIDispatch)));
+                        .WithArguments(TypeNames.ComInterfaceType + "." + nameof(ComInterfaceType.InterfaceIsIDispatch)));
             }
 
             [Fact]
@@ -420,7 +420,7 @@ namespace ComInterfaceGenerator.Unit.Tests
                     _usings + snippet,
                     VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
                         .WithLocation(0)
-                        .WithArguments(TypeNames.ComInterfaceTypeAttribute + "." + nameof(ComInterfaceType.InterfaceIsIInspectable)));
+                        .WithArguments(TypeNames.ComInterfaceType + "." + nameof(ComInterfaceType.InterfaceIsIInspectable)));
             }
 
             [Fact]
@@ -464,7 +464,7 @@ namespace ComInterfaceGenerator.Unit.Tests
                     _usings + snippet,
                     VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
                         .WithLocation(0)
-                        .WithArguments(TypeNames.ComInterfaceTypeAttribute + "." + nameof(ComInterfaceType.InterfaceIsDual)));
+                        .WithArguments(TypeNames.ComInterfaceType + "." + nameof(ComInterfaceType.InterfaceIsDual)));
             }
 
             [Fact]
diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/RuntimeComApiUsageWithSourceGeneratedComTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/RuntimeComApiUsageWithSourceGeneratedComTests.cs
new file mode 100644 (file)
index 0000000..19b90f9
--- /dev/null
@@ -0,0 +1,427 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Threading.Tasks;
+using Xunit;
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpAnalyzerVerifier<
+       Microsoft.Interop.Analyzers.RuntimeComApiUsageWithSourceGeneratedComAnalyzer>;
+
+namespace ComInterfaceGenerator.Unit.Tests
+{
+    [ActiveIssue("https://github.com/dotnet/runtime/issues/60650", TestRuntimes.Mono)]
+    public class RuntimeComApiUsageWithSourceGeneratedComTests
+    {
+        [Fact]
+        public async Task SetComObjectData()
+        {
+            string source = """
+               using System.Runtime.InteropServices;
+               using System.Runtime.InteropServices.Marshalling;
+
+               [GeneratedComInterface]
+               [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+               public interface I
+               {
+               }
+               
+               [GeneratedComClass]
+               public class C : I
+               {
+               }
+
+               public static class Program
+               {
+                   public static void Foo(I i)
+                   {
+                       Marshal.SetComObjectData([|i|], new object(), new object());
+                   }
+                   public static void Foo(C c)
+                   {
+                       Marshal.SetComObjectData([|c|], new object(), new object());
+                   }
+                   public static void Foo(ComObject c)
+                   {
+                       Marshal.SetComObjectData([|c|], new object(), new object());
+                   }
+               }
+               """;
+
+            await VerifyCS.VerifyAnalyzerAsync(source);
+        }
+
+        [Fact]
+        public async Task GetComObjectData()
+        {
+            string source = """
+               using System.Runtime.InteropServices;
+               using System.Runtime.InteropServices.Marshalling;
+
+               [GeneratedComInterface]
+               [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+               public interface I
+               {
+               }
+               
+               [GeneratedComClass]
+               public class C : I
+               {
+               }
+               
+               public static class Program
+               {
+                   public static void Foo(I i)
+                   {
+                       _ = Marshal.GetComObjectData([|i|], new object());
+                   }
+                   public static void Foo(C c)
+                   {
+                       _ = Marshal.GetComObjectData([|c|], new object());
+                   }
+                   public static void Foo(ComObject c)
+                   {
+                       _ = Marshal.GetComObjectData([|c|], new object());
+                   }
+               }
+               """;
+
+            await VerifyCS.VerifyAnalyzerAsync(source);
+        }
+
+        [Fact]
+        public async Task ReleaseComObject()
+        {
+            string source = """
+               using System.Runtime.InteropServices;
+               using System.Runtime.InteropServices.Marshalling;
+               
+               [GeneratedComInterface]
+               [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+               public interface I
+               {
+               }
+               
+               [GeneratedComClass]
+               public class C : I
+               {
+               }
+
+               public static class Program
+               {
+                   public static void Foo(I i)
+                   {
+                       _ = Marshal.ReleaseComObject([|i|]);
+                   }
+                   public static void Foo(C c)
+                   {
+                       _ = Marshal.ReleaseComObject([|c|]);
+                   }
+                   public static void Foo(ComObject c)
+                   {
+                       _ = Marshal.ReleaseComObject([|c|]);
+                   }
+               }
+               """;
+
+            await VerifyCS.VerifyAnalyzerAsync(source);
+        }
+
+        [Fact]
+        public async Task FinalReleaseComObject()
+        {
+            string source = """
+               using System.Runtime.InteropServices;
+               using System.Runtime.InteropServices.Marshalling;
+               
+               [GeneratedComInterface]
+               [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+               public interface I
+               {
+               }
+               
+               [GeneratedComClass]
+               public class C : I
+               {
+               }
+               
+               public static class Program
+               {
+                   public static void Foo(I i)
+                   {
+                       _ = Marshal.FinalReleaseComObject([|i|]);
+                   }
+                   public static void Foo(C c)
+                   {
+                       _ = Marshal.FinalReleaseComObject([|c|]);
+                   }
+                   public static void Foo(ComObject c)
+                   {
+                       _ = Marshal.FinalReleaseComObject([|c|]);
+                   }
+               }
+               """;
+
+            await VerifyCS.VerifyAnalyzerAsync(source);
+        }
+
+        [Fact]
+        public async Task CreateAggregatedObject()
+        {
+            string source = """
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+                
+                [GeneratedComInterface]
+                [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+                public interface I
+                {
+                }
+                
+                [GeneratedComClass]
+                public class C : I
+                {
+                }
+
+                public static class Program
+                {
+                    public static void Foo(nint outer, I i)
+                    {
+                        _ = Marshal.CreateAggregatedObject(outer, (object)[|i|]);
+                        _ = Marshal.CreateAggregatedObject(outer, [|i|]);
+                        _ = Marshal.CreateAggregatedObject<[|I|]>(outer, [|i|]);
+                    }
+                    public static void Foo(nint outer, C c)
+                    {
+                        _ = Marshal.CreateAggregatedObject(outer, (object)[|c|]);
+                        _ = Marshal.CreateAggregatedObject(outer, [|c|]);
+                        _ = Marshal.CreateAggregatedObject<[|C|]>(outer, [|c|]);
+                    }
+                    public static void Foo(nint outer, ComObject c)
+                    {
+                        _ = Marshal.CreateAggregatedObject(outer, (object)[|c|]);
+                        _ = Marshal.CreateAggregatedObject(outer, [|c|]);
+                        _ = Marshal.CreateAggregatedObject<[|ComObject|]>(outer, [|c|]);
+                    }
+                }
+                """;
+
+            await VerifyCS.VerifyAnalyzerAsync(source);
+        }
+
+        [Fact]
+        public async Task CreateWrapperOfType()
+        {
+            string source = """
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+
+                [GeneratedComInterface]
+                [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+                public interface I
+                {
+                }
+
+                [GeneratedComInterface]
+                [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+                public interface J
+                {
+                }
+
+                [GeneratedComClass]
+                public class CI : I
+                {
+                }
+
+                [GeneratedComClass]
+                public class CJ : J
+                {
+                }
+
+                public static class Program
+                {
+                    public static void Foo(I i)
+                    {
+                        _ = Marshal.CreateWrapperOfType([|i|], typeof([|J|]));
+                        _ = Marshal.CreateWrapperOfType<[|I|], [|J|]>([|i|]);
+                        _ = Marshal.CreateWrapperOfType([|i|], typeof([|CI|]));
+                        _ = Marshal.CreateWrapperOfType<[|I|], [|CI|]>([|i|]);
+                        _ = Marshal.CreateWrapperOfType<[|I|], [|ComObject|]>([|i|]);
+                    }
+
+                    public static void Foo(CI i)
+                    {
+                        _ = Marshal.CreateWrapperOfType([|i|], typeof([|J|]));
+                        _ = Marshal.CreateWrapperOfType<[|CI|], [|J|]>([|i|]);
+                        _ = Marshal.CreateWrapperOfType([|i|], typeof([|CJ|]));
+                        _ = Marshal.CreateWrapperOfType<[|CI|], [|CJ|]>([|i|]);
+                        _ = Marshal.CreateWrapperOfType<[|CI|], [|ComObject|]>([|i|]);
+                    }
+
+                    public static void Foo(ComObject i)
+                    {
+                        _ = Marshal.CreateWrapperOfType([|i|], typeof([|J|]));
+                        _ = Marshal.CreateWrapperOfType<[|ComObject|], [|J|]>([|i|]);
+                        _ = Marshal.CreateWrapperOfType([|i|], typeof([|CJ|]));
+                        _ = Marshal.CreateWrapperOfType<[|ComObject|], [|CJ|]>([|i|]);
+                    }
+                }
+                """;
+
+            await VerifyCS.VerifyAnalyzerAsync(source);
+        }        
+
+        [Fact]
+        public async Task GetTypedObjectForIUnknown()
+        {
+            string source = """
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+
+                [GeneratedComInterface]
+                [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+                public interface I
+                {
+                }
+
+                [GeneratedComClass]
+                public class C : I
+                {
+                }
+
+                public static class Program
+                {
+                    public static void Foo(nint unknown)
+                    {
+                        _ = Marshal.GetTypedObjectForIUnknown(unknown, typeof([|I|]));
+                        _ = Marshal.GetTypedObjectForIUnknown(unknown, typeof([|C|]));
+                        _ = Marshal.GetTypedObjectForIUnknown(unknown, typeof([|ComObject|]));
+                    }
+                }
+                """;
+
+            await VerifyCS.VerifyAnalyzerAsync(source);
+        }
+
+        [Fact]
+        public async Task GetIUnknownForObject()
+        {
+            string source = """
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+      
+                [GeneratedComInterface]
+                [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+                public interface I
+                {
+                }
+      
+                [GeneratedComClass]
+                public class C : I
+                {
+                }
+      
+                public static class Program
+                {
+                    public static void Foo(I i)
+                    {
+                        _ = Marshal.GetIUnknownForObject([|i|]);
+                    }
+                    public static void Foo(C c)
+                    {
+                        _ = Marshal.GetIUnknownForObject([|c|]);
+                    }
+                    public static void Foo(ComObject c)
+                    {
+                        _ = Marshal.GetIUnknownForObject([|c|]);
+                    }
+                }
+                """;
+
+            await VerifyCS.VerifyAnalyzerAsync(source);
+        }
+
+        [Fact]
+        public async Task GetIDispatchForObject()
+        {
+            string source = """
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+      
+                [GeneratedComInterface]
+                [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+                public interface I
+                {
+                }
+      
+                [GeneratedComClass]
+                public class C : I
+                {
+                }
+      
+                public static class Program
+                {
+                    public static void Foo(I i)
+                    {
+                        _ = Marshal.GetIDispatchForObject([|i|]);
+                    }
+                    public static void Foo(C c)
+                    {
+                        _ = Marshal.GetIDispatchForObject([|c|]);
+                    }
+                    public static void Foo(ComObject c)
+                    {
+                        _ = Marshal.GetIDispatchForObject([|c|]);
+                    }
+                }
+                """;
+
+            await VerifyCS.VerifyAnalyzerAsync(source);
+        }
+
+        [Fact]
+        public async Task GetComInterfaceForObject()
+        {
+            string source = """
+               using System.Runtime.InteropServices;
+               using System.Runtime.InteropServices.Marshalling;
+      
+               [GeneratedComInterface]
+               [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+               public interface I
+               {
+               }
+      
+               [GeneratedComClass]
+               public class C : I
+               {
+               }
+      
+               public static class Program
+               {
+                   public static void Foo(I i)
+                   {
+                       _ = Marshal.GetComInterfaceForObject([|i|], typeof([|I|]));
+                       _ = Marshal.GetComInterfaceForObject([|i|], typeof([|I|]), CustomQueryInterfaceMode.Allow);
+                       _ = Marshal.GetComInterfaceForObject<[|I|], [|I|]>([|i|]);
+                   }
+
+                   public static void Foo(C c)
+                   {
+                       _ = Marshal.GetComInterfaceForObject([|c|], typeof([|C|]));
+                       _ = Marshal.GetComInterfaceForObject([|c|], typeof([|C|]), CustomQueryInterfaceMode.Allow);
+                       _ = Marshal.GetComInterfaceForObject<[|C|], [|C|]>([|c|]);
+
+                   }
+
+                   public static void Foo(ComObject c)
+                   {
+                       _ = Marshal.GetComInterfaceForObject([|c|], typeof([|ComObject|]));
+                       _ = Marshal.GetComInterfaceForObject([|c|], typeof([|ComObject|]), CustomQueryInterfaceMode.Allow);
+                       _ = Marshal.GetComInterfaceForObject<[|ComObject|], [|ComObject|]>([|c|]);
+                   }
+               }
+               """;
+
+            await VerifyCS.VerifyAnalyzerAsync(source);
+        }
+    }
+}
index 14bb0e4..4bc8194 100644 (file)
@@ -2,6 +2,8 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Threading.Tasks;
@@ -9,6 +11,7 @@ using Microsoft.CodeAnalysis;
 using Microsoft.CodeAnalysis.CSharp;
 using Microsoft.Interop.Analyzers;
 using Xunit;
+using static Microsoft.Interop.Analyzers.ConvertToSourceGeneratedInteropFixer;
 
 using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpCodeFixVerifier<
     Microsoft.Interop.Analyzers.ConvertToLibraryImportAnalyzer,
@@ -19,7 +22,7 @@ namespace LibraryImportGenerator.UnitTests
     [ActiveIssue("https://github.com/dotnet/runtime/issues/60650", TestRuntimes.Mono)]
     public class ConvertToLibraryImportFixerTests
     {
-        private const string ConvertToLibraryImportKey = "ConvertToLibraryImport,";
+        private const string ConvertToLibraryImportKey = "ConvertToLibraryImport";
 
         [Fact]
         public async Task Basic()
@@ -299,7 +302,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceNoSuffix, ConvertToLibraryImportKey);
+            await VerifyCodeFixAsync(source, fixedSourceNoSuffix, ImmutableDictionary<string, Option>.Empty);
             string fixedSourceWithSuffix = $$"""
                 using System.Runtime.InteropServices;
                 partial class Test
@@ -308,7 +311,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceWithSuffix, $"{ConvertToLibraryImportKey}{suffix},");
+            await VerifyCodeFixAsync(source, fixedSourceWithSuffix, new Dictionary<string, Option> { { ConvertToLibraryImportFixer.SelectedSuffixOption, new Option.String(suffix.ToString()) } });
         }
 
         [Fact]
@@ -332,7 +335,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceNoSuffix, ConvertToLibraryImportKey);
+            await VerifyCodeFixAsync(source, fixedSourceNoSuffix, ImmutableDictionary<string, Option>.Empty);
             string fixedSourceWithASuffix = """
 
                 using System.Runtime.InteropServices;
@@ -342,7 +345,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A,");
+            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, new Dictionary<string, Option> { { ConvertToLibraryImportFixer.SelectedSuffixOption, new Option.String("A") } });
             string fixedSourceWithWSuffix = """
 
                 using System.Runtime.InteropServices;
@@ -352,7 +355,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceWithWSuffix, $"{ConvertToLibraryImportKey}W,");
+            await VerifyCodeFixAsync(source, fixedSourceWithWSuffix, new Dictionary<string, Option> { { ConvertToLibraryImportFixer.SelectedSuffixOption, new Option.String("W") } });
         }
 
         [Fact]
@@ -376,7 +379,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceNoSuffix, ConvertToLibraryImportKey);
+            await VerifyCodeFixAsync(source, fixedSourceNoSuffix, ImmutableDictionary<string, Option>.Empty);
             string fixedSourceWithASuffix = """
 
                 using System.Runtime.InteropServices;
@@ -386,7 +389,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A,");
+            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, new Dictionary<string, Option> { { ConvertToLibraryImportFixer.SelectedSuffixOption, new Option.String("A") } });
         }
 
         [Fact]
@@ -412,7 +415,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A,");
+            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, new Dictionary<string, Option> { { ConvertToLibraryImportFixer.SelectedSuffixOption, new Option.String("A") } });
         }
 
         [Fact]
@@ -436,7 +439,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A,");
+            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, new Dictionary<string, Option> { { ConvertToLibraryImportFixer.SelectedSuffixOption, new Option.String("A") } });
         }
 
         [Fact]
@@ -462,7 +465,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A,");
+            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, new Dictionary<string, Option> { { ConvertToLibraryImportFixer.SelectedSuffixOption, new Option.String("A") } });
         }
 
         [Fact]
@@ -486,7 +489,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A,");
+            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, new Dictionary<string, Option> { { ConvertToLibraryImportFixer.SelectedSuffixOption, new Option.String("A") } });
         }
 
         [InlineData(CharSet.Ansi, 'A')]
@@ -510,7 +513,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceNoSuffix, ConvertToLibraryImportKey);
+            await VerifyCodeFixAsync(source, fixedSourceNoSuffix, ImmutableDictionary<string, Option>.Empty);
         }
 
         [Fact]
@@ -534,7 +537,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceNoSuffix, ConvertToLibraryImportKey);
+            await VerifyCodeFixAsync(source, fixedSourceNoSuffix, ImmutableDictionary<string, Option>.Empty);
             string fixedSourceWithASuffix = """
 
                 using System.Runtime.InteropServices;
@@ -544,7 +547,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A,");
+            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, new Dictionary<string, Option> { { ConvertToLibraryImportFixer.SelectedSuffixOption, new Option.String("A") } });
         }
 
         [Fact]
@@ -568,7 +571,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceNoSuffix, ConvertToLibraryImportKey);
+            await VerifyCodeFixAsync(source, fixedSourceNoSuffix, ImmutableDictionary<string, Option>.Empty);
             string fixedSourceWithASuffix = """
 
                 using System.Runtime.InteropServices;
@@ -578,7 +581,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}W,");
+            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, new Dictionary<string, Option> { { ConvertToLibraryImportFixer.SelectedSuffixOption, new Option.String("W") } });
         }
 
         [Fact]
@@ -602,7 +605,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceWithNoAdditionalSuffix, $"{ConvertToLibraryImportKey}A,");
+            await VerifyCodeFixAsync(source, fixedSourceWithNoAdditionalSuffix, new Dictionary<string, Option> { { ConvertToLibraryImportFixer.SelectedSuffixOption, new Option.String("A") } });
         }
 
         [Fact]
@@ -628,7 +631,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, ConvertToLibraryImportKey);
+            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, ImmutableDictionary<string, Option>.Empty);
         }
 
         [Fact]
@@ -652,7 +655,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:MethodA|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, ConvertToLibraryImportKey);
+            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, ImmutableDictionary<string, Option>.Empty);
         }
 
         [Fact]
@@ -678,7 +681,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:Method|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, ConvertToLibraryImportKey);
+            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, ImmutableDictionary<string, Option>.Empty);
         }
 
         [Fact]
@@ -702,7 +705,7 @@ namespace LibraryImportGenerator.UnitTests
                     public static partial void {|CS8795:MethodA|}();
                 }
                 """;
-            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, ConvertToLibraryImportKey);
+            await VerifyCodeFixAsync(source, fixedSourceWithASuffix, ImmutableDictionary<string, Option>.Empty);
         }
 
         [Fact]
@@ -866,7 +869,7 @@ namespace LibraryImportGenerator.UnitTests
             await VerifyCodeFixNoUnsafeAsync(
                 source,
                 fixedSource,
-                $"{ConvertToLibraryImportKey}AddUnsafe,");
+                new Dictionary<string, Option> { { Option.AllowUnsafe, new Option.Bool(true) } });
         }
 
         [Fact]
@@ -906,7 +909,7 @@ namespace LibraryImportGenerator.UnitTests
             await VerifyCodeFixAsync(
                 source,
                 fixedSource,
-                ConvertToLibraryImportKey);
+                ImmutableDictionary<string, Option>.Empty);
         }
 
         [Fact]
@@ -947,12 +950,12 @@ namespace LibraryImportGenerator.UnitTests
             await VerifyCodeFixAsync(
                 source,
                 source,
-                ConvertToLibraryImportKey);
+                ImmutableDictionary<string, Option>.Empty);
 
             await VerifyCodeFixAsync(
                 source,
                 fixedSource,
-                $"{ConvertToLibraryImportKey}{ConvertToLibraryImportAnalyzer.MayRequireAdditionalWork},");
+                new Dictionary<string, Option> { { Option.MayRequireAdditionalWork, new Option.Bool(true) } });
         }
 
         [Fact]
@@ -1013,7 +1016,7 @@ namespace LibraryImportGenerator.UnitTests
             await VerifyCodeFixAsync(
                 source,
                 blittableOnlyFixedSource,
-                ConvertToLibraryImportKey);
+                ImmutableDictionary<string, Option>.Empty);
         }
 
         [Fact]
@@ -1103,7 +1106,7 @@ namespace LibraryImportGenerator.UnitTests
                 source,
                 nonBlittableOnlyFixedSource,
                 allFixedSource,
-                $"{ConvertToLibraryImportKey}{ConvertToLibraryImportAnalyzer.MayRequireAdditionalWork},");
+                new Dictionary<string, Option> { { Option.MayRequireAdditionalWork, new Option.Bool(true) } });
         }
 
         private static async Task VerifyCodeFixAsync(string source, string fixedSource)
@@ -1117,13 +1120,13 @@ namespace LibraryImportGenerator.UnitTests
             await test.RunAsync();
         }
 
-        private static async Task VerifyCodeFixAsync(string source, string fixedSource, string equivalenceKey)
+        private static async Task VerifyCodeFixAsync(string source, string fixedSource, IDictionary<string, Option> options)
         {
             var test = new VerifyCS.Test
             {
                 TestCode = source,
                 FixedCode = fixedSource,
-                CodeActionEquivalenceKey = equivalenceKey,
+                CodeActionEquivalenceKey = Option.CreateEquivalenceKeyFromOptions(ConvertToLibraryImportKey, options.ToImmutableDictionary()),
             };
 
             test.FixedState.MarkupHandling = Microsoft.CodeAnalysis.Testing.MarkupMode.Allow;
@@ -1131,14 +1134,14 @@ namespace LibraryImportGenerator.UnitTests
             await test.RunAsync();
         }
 
-        private static async Task VerifyCodeFixAsync(string source, string fixedSource, string batchFixedSource, string equivalenceKey)
+        private static async Task VerifyCodeFixAsync(string source, string fixedSource, string batchFixedSource, IDictionary<string, Option> options)
         {
             var test = new VerifyCS.Test
             {
                 TestCode = source,
                 FixedCode = fixedSource,
                 BatchFixedCode = batchFixedSource,
-                CodeActionEquivalenceKey = equivalenceKey,
+                CodeActionEquivalenceKey = Option.CreateEquivalenceKeyFromOptions(ConvertToLibraryImportKey, options.ToImmutableDictionary()),
             };
 
             test.FixedState.MarkupHandling = Microsoft.CodeAnalysis.Testing.MarkupMode.Allow;
@@ -1146,13 +1149,13 @@ namespace LibraryImportGenerator.UnitTests
             await test.RunAsync();
         }
 
-        private static async Task VerifyCodeFixNoUnsafeAsync(string source, string fixedSource, string equivalenceKey)
+        private static async Task VerifyCodeFixNoUnsafeAsync(string source, string fixedSource, IDictionary<string, Option> options)
         {
             var test = new TestNoUnsafe
             {
                 TestCode = source,
                 FixedCode = fixedSource,
-                CodeActionEquivalenceKey = equivalenceKey,
+                CodeActionEquivalenceKey = Option.CreateEquivalenceKeyFromOptions(ConvertToLibraryImportKey, options.ToImmutableDictionary()),
             };
 
             await test.RunAsync();