From 531ad9596fef94194744ccfcac7159d1c1ae5e57 Mon Sep 17 00:00:00 2001 From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com> Date: Tue, 1 Aug 2023 16:15:21 -0700 Subject: [PATCH] Add Info warning for int return values (#89601) Adds an 'info' level diagnostic if a GeneratedComInterface method returns int, enum, or a type name "HR" or "HResult" to tell the user that the generated code will put the managed return value as an 'out' parameter on the COM definition. Co-authored-by: Jeremy Koritzinsky --- docs/project/list-of-diagnostics.md | 2 +- .../ComInterfaceGenerator.cs | 6 + .../GeneratorDiagnostics.cs | 14 +- .../gen/Common/Resources/Strings.resx | 8 +- .../gen/Common/Resources/xlf/Strings.cs.xlf | 10 ++ .../gen/Common/Resources/xlf/Strings.de.xlf | 10 ++ .../gen/Common/Resources/xlf/Strings.es.xlf | 10 ++ .../gen/Common/Resources/xlf/Strings.fr.xlf | 10 ++ .../gen/Common/Resources/xlf/Strings.it.xlf | 10 ++ .../gen/Common/Resources/xlf/Strings.ja.xlf | 10 ++ .../gen/Common/Resources/xlf/Strings.ko.xlf | 10 ++ .../gen/Common/Resources/xlf/Strings.pl.xlf | 10 ++ .../Common/Resources/xlf/Strings.pt-BR.xlf | 10 ++ .../gen/Common/Resources/xlf/Strings.ru.xlf | 10 ++ .../gen/Common/Resources/xlf/Strings.tr.xlf | 10 ++ .../Common/Resources/xlf/Strings.zh-Hans.xlf | 10 ++ .../Common/Resources/xlf/Strings.zh-Hant.xlf | 10 ++ .../GeneratorDiagnostics.cs | 1 + .../CompileFails.cs | 123 +++++++++++++++++- .../CSharpSourceGeneratorVerifier.cs | 7 +- 20 files changed, 282 insertions(+), 9 deletions(-) diff --git a/docs/project/list-of-diagnostics.md b/docs/project/list-of-diagnostics.md index 7ea3ee44085..4f78e9e7116 100644 --- a/docs/project/list-of-diagnostics.md +++ b/docs/project/list-of-diagnostics.md @@ -208,7 +208,7 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL | __`SYSLIB1089`__ | _`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator._ | | __`SYSLIB1090`__ | Invalid 'GeneratedComInterfaceAttribute' usage | | __`SYSLIB1091`__ | Method is declared in different partial declaration than the 'GeneratedComInterface' attribute. | -| __`SYSLIB1092`__ | Specified interface derives from two or more 'GeneratedComInterfaceAttribute'-attributed interfaces. | +| __`SYSLIB1092`__ | 'GenerateComInterfaceAttribute' usage not recommended. See aka.ms/GeneratedComInterfaceUsage for recommended usage. | | __`SYSLIB1093`__ | Analysis for COM interface generation has failed | | __`SYSLIB1094`__ | The base COM interface failed to generate source. Code will not be generated for this interface. | | __`SYSLIB1095`__ | Invalid 'GeneratedComClassAttribute' usage | diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs index e1cc737fc8f..9d5105837a9 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs @@ -278,6 +278,12 @@ namespace Microsoft.Interop } else { + if ((returnSwappedSignatureElements[i].ManagedType is SpecialTypeInfo { SpecialType: SpecialType.System_Int32 or SpecialType.System_Enum } or EnumTypeInfo + && returnSwappedSignatureElements[i].MarshallingAttributeInfo.Equals(NoMarshallingInfo.Instance)) + || (returnSwappedSignatureElements[i].ManagedType.FullTypeName.Split('.', ':').LastOrDefault()?.ToLowerInvariant() is "hr" or "hresult")) + { + generatorDiagnostics.ReportDiagnostic(DiagnosticInfo.Create(GeneratorDiagnostics.ComMethodManagedReturnWillBeOutVariable, symbol.Locations[0])); + } // Convert the current element into an out parameter on the native signature // while keeping it at the return position in the managed signature. var managedSignatureAsNativeOut = returnSwappedSignatureElements[i] with diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs index d2648af4ea9..0f3ec3d047d 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs @@ -22,7 +22,7 @@ namespace Microsoft.Interop public const string UnnecessaryMarshallingInfo = Prefix + "1063"; public const string InvalidGeneratedComInterfaceAttributeUsage = Prefix + "1090"; public const string MemberWillNotBeSourceGenerated = Prefix + "1091"; - public const string MultipleComInterfaceBaseTypes = Prefix + "1092"; + public const string NotRecommendedGeneratedComInterfaceUsage = Prefix + "1092"; public const string AnalysisFailed = Prefix + "1093"; public const string BaseInterfaceFailedGeneration = Prefix + "1094"; public const string InvalidGeneratedComClassAttributeUsage = Prefix + "1095"; @@ -340,7 +340,7 @@ namespace Microsoft.Interop /// public static readonly DiagnosticDescriptor MultipleComInterfaceBaseTypes = new DiagnosticDescriptor( - Ids.MultipleComInterfaceBaseTypes, + Ids.InvalidGeneratedComInterfaceAttributeUsage, GetResourceString(nameof(SR.MultipleComInterfaceBaseTypesTitle)), GetResourceString(nameof(SR.MultipleComInterfaceBaseTypesMessage)), Category, @@ -444,6 +444,16 @@ namespace Microsoft.Interop WellKnownDiagnosticTags.Unnecessary }); + /// + public static readonly DiagnosticDescriptor ComMethodManagedReturnWillBeOutVariable = + new DiagnosticDescriptor( + Ids.NotRecommendedGeneratedComInterfaceUsage, + GetResourceString(nameof(SR.ComMethodReturningIntWillBeOutParameterTitle)), + GetResourceString(nameof(SR.ComMethodReturningIntWillBeOutParameterMessage)), + Category, + DiagnosticSeverity.Info, + isEnabledByDefault: true); + /// /// Report diagnostic for invalid configuration for string marshalling. /// diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx index f03a1e31d3e..5dd131c0afa 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx @@ -880,4 +880,10 @@ The `[Out]` attribute is only supported on array parameters and parameters marshalled by pinning. Consider using 'out' or 'ref' keywords to make the parameter mutable. - \ No newline at end of file + + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + + + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + + diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.cs.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.cs.xlf index 710fbded21b..5dab1b24b59 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.cs.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.cs.xlf @@ -147,6 +147,16 @@ Hostování .NET COM s EnableComHosting nepodporuje rozhraní s generatedComInterfaceAttribute + + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + + + + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + + Source-generated COM will ignore any configuration that is not supported. Model COM vygenerovaný zdrojem bude ignorovat všechny nepodporované konfigurace. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.de.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.de.xlf index e936db000e8..49a475c5dca 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.de.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.de.xlf @@ -147,6 +147,16 @@ Das .NET COM-Hosting mit "EnableComHosting" unterstützt keine Schnittstellen mit "GeneratedComInterfaceAttribute". + + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + + + + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + + Source-generated COM will ignore any configuration that is not supported. Quellgeneriertes COM ignoriert alle Konfigurationen, die nicht unterstützt werden. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.es.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.es.xlf index b839f3872e5..21b41f24a83 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.es.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.es.xlf @@ -147,6 +147,16 @@ El hospedaje COM de .NET con “EnableComHosting” no admite interfaces con “GeneratedComInterfaceAttribute” + + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + + + + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + + Source-generated COM will ignore any configuration that is not supported. COM generado por el origen omitirá cualquier configuración que no se admita. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.fr.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.fr.xlf index 2f8bdf81310..f3aa7dac375 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.fr.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.fr.xlf @@ -147,6 +147,16 @@ L'hébergement .NET COM avec 'EnableComHosting' ne prend pas en charge les interfaces avec 'GeneratedComInterfaceAttribute' + + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + + + + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + + Source-generated COM will ignore any configuration that is not supported. COM généré par la source ignore toute configuration qui n’est pas prise en charge. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.it.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.it.xlf index 121b7e07fb4..ac87db54081 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.it.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.it.xlf @@ -147,6 +147,16 @@ L'hosting COM .NET con 'EnableComHosting' non supporta le interfacce con 'GeneratedComInterfaceAttribute'. + + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + + + + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + + Source-generated COM will ignore any configuration that is not supported. I COM generati dall'origine ignoreranno qualsiasi configurazione non supportata. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ja.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ja.xlf index 6b2e28daa1c..867f5472f69 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ja.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ja.xlf @@ -147,6 +147,16 @@ 'EnableComHosting' を使用した .NET COM ホスティングでは、'GeneratedComInterfaceAttribute' のインターフェイスはサポートされていません + + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + + + + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + + Source-generated COM will ignore any configuration that is not supported. ソース生成済みの COM は、サポートされていない構成を無視します。 diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ko.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ko.xlf index 271742c3edc..c04b1253058 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ko.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ko.xlf @@ -147,6 +147,16 @@ 'EnableComHosting'을 사용한 .NET COM 호스팅은 'GeneratedComInterfaceAttribute'를 사용한 인터페이스를 지원하지 않습니다. + + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + + + + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + + Source-generated COM will ignore any configuration that is not supported. 소스 생성 COM은 지원되지 않는 구성을 무시합니다. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pl.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pl.xlf index 9ebb95b2274..6a4a6f7ba98 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pl.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pl.xlf @@ -147,6 +147,16 @@ Hosting modelu COM platformy .NET z elementem „EnableComHosting” nie obsługuje interfejsów z atrybutem „GeneratedComInterfaceAttribute” + + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + + + + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + + Source-generated COM will ignore any configuration that is not supported. COM wygenerowany przez źródło zignoruje każdą konfigurację, która nie jest obsługiwana. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pt-BR.xlf index 35ad76dd03d..6ae9c3061d4 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pt-BR.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.pt-BR.xlf @@ -147,6 +147,16 @@ A hospedagem .NET COM com 'EnableComHosting' não dá suporte a interfaces com 'GeneratedComInterfaceAttribute' + + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + + + + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + + Source-generated COM will ignore any configuration that is not supported. Um COM gerado pela origem ignorará qualquer configuração sem suporte. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ru.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ru.xlf index 30246aa2f2d..2f16b177e22 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ru.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.ru.xlf @@ -147,6 +147,16 @@ Размещение .NET COM с "EnableComHosting" не поддерживает интерфейсы с "GeneratedComInterfaceAttribute" + + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + + + + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + + Source-generated COM will ignore any configuration that is not supported. Модель COM генератора исходного кода будет игнорировать любую неподдерживаемую конфигурацию. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.tr.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.tr.xlf index 491a8ee1836..521f0b8cb73 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.tr.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.tr.xlf @@ -147,6 +147,16 @@ 'EnableComHosting' ile barındırma .NET COM, 'GeneratedComInterfaceAttribute' ile arabirimleri desteklemez + + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + + + + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + + Source-generated COM will ignore any configuration that is not supported. Kaynak tarafından oluşturulan COM, desteklenmeyen herhangi bir yapılandırmayı yok sayar. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hans.xlf index 093f59852ac..a303503da5f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hans.xlf @@ -147,6 +147,16 @@ 具有“EnableComHosting”的 .NET COM 托管不支持具有“GeneratedComInterfaceAttribute”的接口 + + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + + + + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + + Source-generated COM will ignore any configuration that is not supported. 源生成的 COM 将忽略任何不受支持的配置。 diff --git a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hant.xlf index dcdbc48a12a..adf2ea22b53 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/xlf/Strings.zh-Hant.xlf @@ -147,6 +147,16 @@ 以 'EnableComHosting' 裝載的 .NET COM 不支援具有 'GeneratedComInterfaceAttribute' 的介面 + + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + The return value in the managed definition will be converted to an 'out' parameter when calling the unmanaged COM method. If the return value is intended to be the HRESULT code returned by the unmanaged COM method, use '[PreserveSig]' on the method. + + + + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + The return value in the managed definition will be converted to an additional 'out' parameter at the end of the parameter list when calling the unmanaged COM method. + + Source-generated COM will ignore any configuration that is not supported. 来源產生的 COM 將會略過任何不支援的設定。 diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs index afab0f9d978..140775be274 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs @@ -22,6 +22,7 @@ namespace Microsoft.Interop public const string RequiresAllowUnsafeBlocks = Prefix + "1062"; public const string UnnecessaryMarshallingInfo = Prefix + "1063"; + public const string NotRecommendedGeneratedComInterfaceUsage = Prefix + "1092"; } private const string Category = "LibraryImportGenerator"; diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CompileFails.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CompileFails.cs index 4fbe5cabbcd..a0f11769073 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CompileFails.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CompileFails.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; using System.Threading.Tasks; using Microsoft.CodeAnalysis; @@ -975,5 +974,127 @@ namespace ComInterfaceGenerator.Unit.Tests test.ExpectedDiagnostics.Add(expectedDiagnostic); await test.RunAsync(); } + + public static IEnumerable IntAndEnumReturnTypeSnippets() + { + var diagnostic = VerifyComInterfaceGenerator.Diagnostic(GeneratorDiagnostics.ComMethodManagedReturnWillBeOutVariable).WithLocation(0); + var enumDecl = $$""" + internal enum Err + { + Val1, Val2 + } + """; + var structDeclHR = $$""" + internal struct HR + { + int hr; + } + """; + var structDeclHResult = $$""" + internal struct HResult + { + int hr; + } + """; + var enumReturn = Template("Err", enumDecl, ""); + var intReturn = Template("int", "", ""); + var floatReturn = Template("float", "", ""); + var structHrReturn = Template("HR", structDeclHR, ""); + var structHResultReturn = Template("HResult", structDeclHResult, ""); + yield return new object[] { + ID(), + enumReturn, + new DiagnosticResult[] { diagnostic } + }; + yield return new object[] { + ID(), + intReturn, + new DiagnosticResult[] { diagnostic } + }; + yield return new object[] { + ID(), + structHrReturn, + new DiagnosticResult[] { diagnostic } + }; + yield return new object[] { + ID(), + structHResultReturn, + new DiagnosticResult[] { diagnostic } + }; + yield return new object[] { + ID(), + floatReturn, + new DiagnosticResult[] { } + }; + + var enumReturnPreserveSig = Template("Err", enumDecl, "[PreserveSig]"); + var intReturnPreserveSig = Template("int", "", "[PreserveSig]"); + var structHrPreserveSig = Template("HR", structDeclHR, "[PreserveSig]"); + var structHResultPreserveSig = Template("HResult", structDeclHResult, "[PreserveSig]"); + yield return new object[] { + ID(), + enumReturnPreserveSig, + new DiagnosticResult[] { } + }; + yield return new object[] { + ID(), + intReturnPreserveSig, + new DiagnosticResult[] { } + }; + yield return new object[] { + ID(), + structHrPreserveSig, + new DiagnosticResult[] { } + }; + yield return new object[] { + ID(), + structHResultPreserveSig, + new DiagnosticResult[] { } + }; + + var intReturnMarshalAs = Template("int", "", "[return: MarshalAs(UnmanagedType.I4)]"); + yield return new object[] { + ID(), + intReturnMarshalAs, + new DiagnosticResult[] { } + }; + + string Template(string type, string typedef, string attribute) + { + return $$""" + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + [GeneratedComInterface] + [Guid("0DB41042-0255-4CDD-B73A-9C5D5F31303D")] + partial interface I + { + {{attribute}} + {{type}} {|#0:Method|}(); + } + {{typedef}} + """; + } + } + [Theory] + [MemberData(nameof(IntAndEnumReturnTypeSnippets))] + async Task ValidateIntReturnTypeShowsInfo(string id, string source, DiagnosticResult[] diagnostics) + { + _ = id; + + var test = new VerifyComInterfaceGenerator.Test(referenceAncillaryInterop: false) + { + TestState = + { + Sources = + { + ("Source.cs", source) + }, + }, + TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck | TestBehaviors.SkipGeneratedCodeCheck, + }; + test.ExpectedDiagnostics.AddRange(diagnostics); + test.DisabledDiagnostics.Remove(GeneratorDiagnostics.Ids.NotRecommendedGeneratedComInterfaceUsage); + await test.RunAsync(); + } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/Common/Verifiers/CSharpSourceGeneratorVerifier.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/Verifiers/CSharpSourceGeneratorVerifier.cs index 1af721d9dfc..84bd897adc6 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/Common/Verifiers/CSharpSourceGeneratorVerifier.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/Common/Verifiers/CSharpSourceGeneratorVerifier.cs @@ -4,14 +4,11 @@ using System; using System.Collections.Immutable; using System.Diagnostics; -using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Testing; -using Microsoft.CodeAnalysis.CSharp.Testing.XUnit; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Testing; using Microsoft.CodeAnalysis.Testing.Verifiers; @@ -49,6 +46,7 @@ namespace Microsoft.Interop.UnitTests.Verifiers TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck }; + test.DisabledDiagnostics.Add(GeneratorDiagnostics.Ids.NotRecommendedGeneratedComInterfaceUsage); test.ExpectedDiagnostics.AddRange(expected); await test.RunAsync(CancellationToken.None); } @@ -106,12 +104,13 @@ namespace Microsoft.Interop.UnitTests.Verifiers SolutionTransforms.Add(CSharpVerifierHelper.GetTargetFrameworkAnalyzerOptionsProviderTransform(targetFramework)); } public Test(bool referenceAncillaryInterop) - :this(TestTargetFramework.Net) + : this(TestTargetFramework.Net) { if (referenceAncillaryInterop) { TestState.AdditionalReferences.Add(TestUtils.GetAncillaryReference()); } + DisabledDiagnostics.Add(GeneratorDiagnostics.Ids.NotRecommendedGeneratedComInterfaceUsage); SolutionTransforms.Add(CSharpVerifierHelper.GetAllDiagonsticsEnabledTransform(GetDiagnosticAnalyzers())); }