From b58abc59229708fe4dc42d18872fe1bf750e988d Mon Sep 17 00:00:00 2001 From: Jackson Schuster Date: Mon, 21 Aug 2023 22:47:03 +0000 Subject: [PATCH 1/5] wip --- .../gen/Common/Resources/Strings.resx | 65 ++++---- .../gen/Common/Resources/xlf/Strings.cs.xlf | 15 ++ .../gen/Common/Resources/xlf/Strings.de.xlf | 15 ++ .../gen/Common/Resources/xlf/Strings.es.xlf | 15 ++ .../gen/Common/Resources/xlf/Strings.fr.xlf | 15 ++ .../gen/Common/Resources/xlf/Strings.it.xlf | 15 ++ .../gen/Common/Resources/xlf/Strings.ja.xlf | 15 ++ .../gen/Common/Resources/xlf/Strings.ko.xlf | 15 ++ .../gen/Common/Resources/xlf/Strings.pl.xlf | 15 ++ .../Common/Resources/xlf/Strings.pt-BR.xlf | 15 ++ .../gen/Common/Resources/xlf/Strings.ru.xlf | 15 ++ .../gen/Common/Resources/xlf/Strings.tr.xlf | 15 ++ .../Common/Resources/xlf/Strings.zh-Hans.xlf | 15 ++ .../Common/Resources/xlf/Strings.zh-Hant.xlf | 15 ++ ...ributedMarshallingModelGeneratorFactory.cs | 11 +- .../ByValueContentsMarshalKindValidator.cs | 1 + .../ByValueMarshalKindSupportDescriptor.cs | 148 +++++++----------- .../Marshalling/GeneratorDiagnostic.cs | 13 ++ .../Marshalling/MarshallingGenerator.cs | 4 + .../StaticPinnableManagedValueMarshaller.cs | 2 +- .../BestPracticeMessagesTests.cs | 28 ++++ .../ComInterfaceGenerator.Unit.Tests.csproj | 1 + .../TestAssets/SharedTypes/SharedTypes.csproj | 2 +- 23 files changed, 342 insertions(+), 128 deletions(-) create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs 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 ebf0170e328752..77f189684d3544 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx @@ -1,17 +1,17 @@  - @@ -889,4 +889,13 @@ This type will be treated as a struct in the native signature, not as a native HRESULT - \ No newline at end of file + + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + + + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + + + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + + 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 aba6380486a3b7..2a15cc5e3f49b8 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 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + + + + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + + 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. Vrácená hodnota ve spravované definici se při volání nespravované metody COM převede na parametr out. Pokud má být návratovou hodnotou kód HRESULT vrácený nespravovanou metodou COM, použijte u metody [PreserveSig]. @@ -917,6 +927,11 @@ Typ {0}určuje, že podporuje zařazování ve směru „Out“, ale neposkytuje metodu ToManaged, která vrací spravovaný typ + + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + + 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. GeneratedComInterfaceAttribute a GeneratedComClassAttribute vyžadují nebezpečný kód. Projekt se musí aktualizovat na <AllowUnsafeBlocks>true</AllowUnsafeBlocks>. 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 6b978f9aff5a9f..85de74504e4ae0 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 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + + + + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + + 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. Der Rückgabewert in der verwalteten Definition wird beim Aufrufen der nicht verwalteten COM-Methode in einen out-Parameter konvertiert. Wenn als Rückgabewert der von der nicht verwalteten COM-Methode zurückgegebene HRESULT-Code eingesetzt werden soll, verwenden Sie "[PreserveSig]" für die Methode. @@ -917,6 +927,11 @@ Der Typ \"{0}\" gibt an, dass das Marshalling in der Out-Richtung unterstützt wird. Er stellt jedoch keine ToManaged-Methode bereit, die den verwalteten Typ zurückgibt. + + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + + 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. 'GeneratedComInterfaceAttribute' und 'GeneratedComClassAttribute' erfordern unsicheren Code. Das Projekt muss mit '<AllowUnsafeBlocks>wahr</AllowUnsafeBlocks>' aktualisiert 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 077827dbf7ef9b..b8f615258f6afd 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 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + + + + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + + 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. El valor devuelto en la definición administrada se convertirá en un parámetro “out” al llamar al método COM no administrado. Si el valor devuelto debe ser el código HRESULT devuelto por el método COM no administrado, use “[PreserveSig]” en el método. @@ -917,6 +927,11 @@ El tipo “{0}” especifica que admite la serialización en la dirección “Out”, pero no proporciona un método “ToManaged” que devuelva el tipo administrado + + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + + 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. "GeneratedComInterfaceAttribute" y "GeneratedComClassAttribute" requieren código no seguro. El proyecto debe actualizarse con "<AllowUnsafeBlocks>true</AllowUnsafeBlocks>". 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 7b06fbb9966ce1..d5c2a0aef06b88 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 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + + + + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + + 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. La valeur de retour dans la définition managée est convertie en paramètre 'out' lors de l’appel de la méthode COM non managée. Si la valeur de retour doit être le code HRESULT retourné par la méthode COM non managée, utilisez '[PreserveSig]' sur la méthode. @@ -917,6 +927,11 @@ Le type « {0} » spécifie qu’il prend en charge le marshaling dans la direction « Out », mais il ne fournit pas de méthode « ToManaged » qui retourne le type managé + + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + + 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. « GeneratedComInterfaceAttribute » et « GeneratedComClassAttribute » nécessitent du code non sécurisé. Le projet doit être mis à jour avec « <AllowUnsafeBlocks>true</AllowUnsafeBlocks> ». 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 ee4ead36b3e114..35d79dac1fa795 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 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + + + + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + + 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. Il valore restituito nella definizione gestita verrà convertito in un parametro 'out' quando si chiama il metodo COM non gestito. Se il valore restituito deve essere il codice HRESULT restituito dal metodo COM non gestito, utilizzare '[PreserveSig]' sul metodo. @@ -917,6 +927,11 @@ Il tipo '{0}' specifica che supporta il marshalling nella direzione 'Out', ma non fornisce un metodo 'ToManaged' che restituisce il tipo gestito + + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + + 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. GeneratedComInterfaceAttribute e 'GeneratedComClassAttribute' richiedono codice non gestito. Il progetto deve essere aggiornato con '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. 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 9c12755cb80b44..12c47e3084a678 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 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + + + + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + + 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. マネージド定義の戻り値は、アンマネージド COM メソッドを呼び出すときに 'out' パラメーターに変換されます。戻り値を、アンマネージド COM メソッドによって返される HRESULT コードにする場合は、メソッドで '[PreserveSig]' を使用してください。 @@ -917,6 +927,11 @@ 型 '{0}' は、'Out' 方向のマーシャリングをサポートしますが、マネージド型を返す 'ToManaged' メソッドは指定されません + + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + + 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. 'GeneratedComInterfaceAttribute' および 'GeneratedComClassAttribute' にはアンセーフ コードが必要です。プロジェクトは '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>' で更新する必要があります。 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 53b72d47f60fa3..0bf758a06ab444 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 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + + + + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + + 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. 관리 정의의 반환 값은 관리되지 않는 COM 메서드를 호출할 때 'out' 매개 변수로 변환됩니다. 반환 값이 관리되지 않는 COM 메서드에서 반환된 HRESULT 코드인 경우 메서드에서 '[PreserveSig]'를 사용하세요. @@ -917,6 +927,11 @@ 형식 '{0}'은(는) 'Out' 방향으로 마샬링을 지원하도록 지정하지만 관리 형식을 반환하는 'ToManaged' 메서드를 제공하지 않습니다. + + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + + 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. 'GeneratedComInterfaceAttribute' 및 'GeneratedComClassAttribute'에는 안전하지 않은 코드가 필요합니다. 프로젝트를 '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'로 업데이트해야 합니다. 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 fb6cf9f172c21b..a01b85625b88e9 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 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + + + + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + + 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. Wartość zwracana w definicji zarządzanej zostanie przekonwertowana na parametr „out” podczas wywoływania niezarządzanej metody COM. Jeśli wartość zwracana ma być kodem HRESULT zwracanym przez niezarządzaną metodę COM, należy użyć „[PreserveSig]” w metodzie. @@ -917,6 +927,11 @@ Typ „{0}” określa, że obsługuje skierowanie w kierunku „Out”, ale nie zapewnia metody „ToManaged”, która zwraca typ zarządzany + + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + + 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. Atrybut „GeneratedComInterfaceAttribute” i „GeneratedComClassAttribute” wymagają niebezpiecznego kodu. Projekt musi zostać zaktualizowany za pomocą polecenia „<AllowUnsafeBlocks>true</AllowUnsafeBlocks>”. 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 8d2e606d2d0307..87ef939e0b1211 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 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + + + + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + + 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. O valor de retorno na definição gerenciada será convertido em um parâmetro 'out' ao chamar o método COM não gerenciado. Se o valor de retorno for o código HRESULT retornado pelo método COM não gerenciado, use '[PreserveSig]' no método. @@ -917,6 +927,11 @@ O tipo '{0}' especifica que ele dá suporte a marshalling na direção 'Out', mas não fornece um método 'ToManaged' que retorna o tipo gerenciado + + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + + 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. "GeneratedComInterfaceAttribute" e "GeneratedComClassAttribute" exigem código não seguro. O projeto deve ser atualizado com "<AllowUnsafeBlocks>true</AllowUnsafeBlocks>". 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 fca13d2b25e7f6..640c7cc028a4d7 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 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + + + + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + + 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. Возвращаемое значение в управляемом определении будет преобразовано в параметр "out" при вызове неуправляемого метода COM. Если возвращаемое значение должно быть кодом HRESULT, возвращаемым неуправляемым COM-методом, используйте "[PreserveSig]" в методе. @@ -917,6 +927,11 @@ Тип \"{0}\" указывает, что поддерживает маршализацию в направлении \"наружу\", но не предоставляет метод \"ToManaged\", который возвращает управляемый тип + + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + + 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. Для "GeneratedComInterfaceAttribute" и "GeneratedComClassAttribute" требуется небезопасный код. Проект необходимо обновить с использованием значения "<AllowUnsafeBlocks>true</AllowUnsafeBlocks>". 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 44d2a4a4cbadd3..139b29340add96 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 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + + + + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + + 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. Yönetilen tanımdaki dönüş değeri, yönetilmeyen COM yöntemi çağrılırken 'out' parametresine dönüştürülür. Dönüş değerinin yönetilmeyen COM yöntemi tarafından döndürülen HRESULT kodu olması amaçlanmışsa, yöntemde '[PreserveSig]' kullanın. @@ -917,6 +927,11 @@ '{0}' türü, 'Out' yönünde sıralamayı desteklediğini belirtiyor, ancak yönetilen türü döndüren bir 'ToManaged' metodu sağlamıyor + + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + + 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. 'GeneratedComInterfaceAttribute' ve 'GeneratedComClassAttribute' güvenli olmayan kod gerektiriyor. Projenin '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>' ile güncelleştirilmiş olması gerekiyor. 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 e6fbf9115aec2d..170703c0f6916b 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 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + + + + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + + 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. 调用非托管 COM 方法时,托管定义中的返回值将转换为 "out" 参数。如果返回值是非托管 COM 方法返回的 HRESULT 代码,请对方法使用 "[PreserveSig]"。 @@ -917,6 +927,11 @@ 类型“{0}”指定它支持按 “Out” 方向进行封送,但不提供返回托管类型的 “ToManaged” 方法 + + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + + 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. “GeneratedComInterfaceAttribute”和“GeneratedComClassAttribute”需要不安全代码。必须将项目更新为“<AllowUnsafeBlocks>true</AllowUnsafeBlocks>”。 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 528339678cefdb..8f782b0c2d68da 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 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + + + + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + + 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. 呼叫未受控 COM 方法時,受控定義中的傳回值將轉換為 'out' 參數。如果傳回值預期是未受控 COM 方法傳回的 HRESULT 代碼,請在方法上使用 '[PreserveSig]'。 @@ -917,6 +927,11 @@ 類型 '{0}' 指定它支援以 'Out' 方向排列,但未提供傳回受管理類型的 'ToManaged' 方法 + + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. + + 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. 'GeneratedComInterfaceAttribute' 和 'GeneratedComClassAttribute' 需要不安全的程式碼。專案必須以 '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>' 更新。 diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs index 73b8cd8eb901a9..69180eca11c190 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs @@ -431,17 +431,10 @@ private ResolvedGenerator CreateNativeCollectionMarshaller( { byValueMarshalKindSupport = ByValueMarshalKindSupportDescriptor.Default; } - else if (!elementIsBlittable || ElementTypeIsSometimesNonBlittable(elementInfo)) - { - // If the type is not blittable or is sometimes not blittable, we will generate different code when the attributes are provided. - byValueMarshalKindSupport = ByValueMarshalKindSupportDescriptor.ArrayParameter; - } else { - // If the type is always blittable, we'll generate the same code regardless of the attributes, - // but we'll allow them to make it easier to transition to source-generated code and allow users to be clear about expectations - // for values in pre-allocated buffers. - byValueMarshalKindSupport = ByValueMarshalKindSupportDescriptor.PinnedParameter; + // If we have an array, we will use the Array [In, Out] support descriptor + byValueMarshalKindSupport = ByValueMarshalKindSupportDescriptor.ArrayParameter; } // Elements in the collection must be blittable to use the pinnable marshaller. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs index 5cc2a8f9a9b261..f96da7cf28c513 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs @@ -41,6 +41,7 @@ private static ResolvedGenerator ValidateByValueMarshalKind(TypePositionInfo inf ByValueMarshalKindSupport.Supported => generator, ByValueMarshalKindSupport.NotSupported => ResolvedGenerator.ResolvedWithDiagnostics(s_forwarder, generator.Diagnostics.Add(diagnostic!)), ByValueMarshalKindSupport.Unnecessary => generator with { Diagnostics = generator.Diagnostics.Add(diagnostic!) }, + ByValueMarshalKindSupport.NotRecommended => generator with { Diagnostics = generator.Diagnostics.Add(diagnostic!) }, _ => throw new UnreachableException() }; } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs index 1f859d34ff919b..052ef87d9c608c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs @@ -6,37 +6,64 @@ namespace Microsoft.Interop { + public record struct ByValueMarshalKindSupportVariant(ByValueMarshalKindSupport Support, string? details) + { + public ByValueMarshalKindSupport GetSupport(TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) + { + diagnostic = Support switch + { + ByValueMarshalKindSupport.Supported => null, + ByValueMarshalKindSupport.NotRecommended => + new GeneratorDiagnostic.NotRecommended(info, context) + { + Details = details + }, + ByValueMarshalKindSupport.Unnecessary => + new GeneratorDiagnostic.UnnecessaryData( + info, + context, + ImmutableArray.Create(info.ByValueMarshalAttributeLocations.OutLocation)) + { + UnnecessaryDataName = SR.InOutAttributes, + UnnecessaryDataDetails = details + }, + ByValueMarshalKindSupport.NotSupported => + new GeneratorDiagnostic.NotSupported(info, context) + { + NotSupportedDetails = details + }, + _ => throw new UnreachableException() + }; + return Support; + } + } + /// /// Provides an implementation of through /// public record ByValueMarshalKindSupportDescriptor( - ByValueMarshalKindSupport InSupport, string? InSupportDetails, - ByValueMarshalKindSupport OutSupport, string? OutSupportDetails, - ByValueMarshalKindSupport InOutSupport, string? InOutSupportDetails) + ByValueMarshalKindSupportVariant DefaultSupport, + ByValueMarshalKindSupportVariant InSupport, + ByValueMarshalKindSupportVariant OutSupport, + ByValueMarshalKindSupportVariant InOutSupport) { /// /// A default for by value parameters. [In] is allowed, but unnecessary. Out is not allowed. /// public static readonly ByValueMarshalKindSupportDescriptor Default = new ByValueMarshalKindSupportDescriptor( - InSupport: ByValueMarshalKindSupport.Unnecessary, InSupportDetails: SR.InAttributeOnlyIsDefault, - OutSupport: ByValueMarshalKindSupport.NotSupported, OutSupportDetails: SR.OutAttributeNotSupportedOnByValueParameters, - InOutSupport: ByValueMarshalKindSupport.NotSupported, InOutSupportDetails: SR.OutAttributeNotSupportedOnByValueParameters); + DefaultSupport: new(ByValueMarshalKindSupport.Supported, null), + InSupport: new(ByValueMarshalKindSupport.NotSupported, SR.OutAttributeNotSupportedOnByValueParameters), + OutSupport: new(ByValueMarshalKindSupport.NotSupported, SR.OutAttributeNotSupportedOnByValueParameters), + InOutSupport: new(ByValueMarshalKindSupport.NotSupported, SR.OutAttributeNotSupportedOnByValueParameters)); /// - /// A default for by value array parameters. [In] is allowed, but unnecessary. Out is allowed. + /// A default for by value array parameters. Default is allowed, but Not Recommended. [In], [Out], and [In, Out] are allowed /// public static readonly ByValueMarshalKindSupportDescriptor ArrayParameter = new ByValueMarshalKindSupportDescriptor( - InSupport: ByValueMarshalKindSupport.Unnecessary, InSupportDetails: SR.InAttributeOnlyIsDefault, - OutSupport: ByValueMarshalKindSupport.Supported, OutSupportDetails: null, - InOutSupport: ByValueMarshalKindSupport.Supported, InOutSupportDetails: null); - - /// - /// A default for pinned parameters. [In] is allowed, but unnecessary. Out is allowed. - /// - public static readonly ByValueMarshalKindSupportDescriptor PinnedParameter = new ByValueMarshalKindSupportDescriptor( - InSupport: ByValueMarshalKindSupport.Unnecessary, InSupportDetails: SR.InAttributeOnlyIsDefault, - OutSupport: ByValueMarshalKindSupport.Supported, OutSupportDetails: null, - InOutSupport: ByValueMarshalKindSupport.Supported, InOutSupportDetails: null); + DefaultSupport: new(ByValueMarshalKindSupport.NotRecommended, SR.PreferExplicitInOutAttributesOnArrays), + InSupport: new(ByValueMarshalKindSupport.Supported, null), + OutSupport: new(ByValueMarshalKindSupport.Supported, null), + InOutSupport: new(ByValueMarshalKindSupport.Supported, null)); /// /// Returns the support for the ByValueContentsMarshalKind, and if it is not , diagnostic is not null @@ -51,79 +78,22 @@ public ByValueMarshalKindSupport GetSupport(ByValueContentsMarshalKind marshalKi }; return ByValueMarshalKindSupport.NotSupported; } - switch (marshalKind) + // Do return types ever get here? + // Return types should never have In or Out attributes + if (info.ManagedIndex < 0 && marshalKind is ByValueContentsMarshalKind.Default) { - case ByValueContentsMarshalKind.Default: - diagnostic = null; - return ByValueMarshalKindSupport.Supported; - case ByValueContentsMarshalKind.Out: - diagnostic = OutSupport switch - { - ByValueMarshalKindSupport.Supported => null, - ByValueMarshalKindSupport.Unnecessary - => new GeneratorDiagnostic.UnnecessaryData( - info, - context, - ImmutableArray.Create(info.ByValueMarshalAttributeLocations.OutLocation)) - { - UnnecessaryDataName = SR.InOutAttributes, - UnnecessaryDataDetails = OutSupportDetails - }, - ByValueMarshalKindSupport.NotSupported - => new GeneratorDiagnostic.NotSupported( - info, - context) - { NotSupportedDetails = OutSupportDetails }, - _ => throw new UnreachableException($"Unexpected {nameof(ByValueMarshalKindSupport)} Variant: {InOutSupport}") - }; - return OutSupport; - case ByValueContentsMarshalKind.In: - diagnostic = InSupport switch - { - ByValueMarshalKindSupport.Supported => null, - ByValueMarshalKindSupport.Unnecessary - => new GeneratorDiagnostic.UnnecessaryData( - info, - context, - ImmutableArray.Create(info.ByValueMarshalAttributeLocations.InLocation)) - { - UnnecessaryDataName = SR.InOutAttributes, - UnnecessaryDataDetails = InSupportDetails - }, - ByValueMarshalKindSupport.NotSupported - => new GeneratorDiagnostic.NotSupported( - info, - context) - { NotSupportedDetails = InSupportDetails }, - _ => throw new UnreachableException($"Unexpected {nameof(ByValueMarshalKindSupport)} Variant: {InOutSupport}") - }; - return InSupport; - case ByValueContentsMarshalKind.InOut: - diagnostic = InOutSupport switch - { - ByValueMarshalKindSupport.Supported => null, - ByValueMarshalKindSupport.Unnecessary - => new GeneratorDiagnostic.UnnecessaryData( - info, - context, - ImmutableArray.Create( - info.ByValueMarshalAttributeLocations.InLocation, - info.ByValueMarshalAttributeLocations.OutLocation)) - { - UnnecessaryDataName = SR.InOutAttributes, - UnnecessaryDataDetails = InOutSupportDetails - }, - ByValueMarshalKindSupport.NotSupported - => new GeneratorDiagnostic.NotSupported( - info, - context) - { NotSupportedDetails = InOutSupportDetails }, - _ => throw new UnreachableException($"Unexpected {nameof(ByValueMarshalKindSupport)} Variant: {InOutSupport}") - }; - return InOutSupport; - default: - throw new UnreachableException($"Unexpected {nameof(ByValueContentsMarshalKind)} variant: {marshalKind}"); + diagnostic = null; + return ByValueMarshalKindSupport.Supported; } + + return marshalKind switch + { + ByValueContentsMarshalKind.Default => DefaultSupport.GetSupport(info, context, out diagnostic), + ByValueContentsMarshalKind.In => InSupport.GetSupport(info, context, out diagnostic), + ByValueContentsMarshalKind.Out => OutSupport.GetSupport(info, context, out diagnostic), + ByValueContentsMarshalKind.InOut => InOutSupport.GetSupport(info, context, out diagnostic), + _ => throw new UnreachableException() + }; } } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/GeneratorDiagnostic.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/GeneratorDiagnostic.cs index 22444e79824c9b..02820335ec176e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/GeneratorDiagnostic.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/GeneratorDiagnostic.cs @@ -62,5 +62,18 @@ public override DiagnosticInfo ToDiagnosticInfo(DiagnosticDescriptor descriptor, UnnecessaryDataDetails ?? ""); } } + + public sealed record NotRecommended(TypePositionInfo TypePositionInfo, StubCodeContext StubCodeContext) : GeneratorDiagnostic(TypePositionInfo, StubCodeContext, isFatal: false) + { + public string? Details { get; init; } + + public override DiagnosticInfo ToDiagnosticInfo(DiagnosticDescriptor descriptor, Location location, string elementName) + { + return DiagnosticInfo.Create( + descriptor, + location, + Details); + } + } } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs index f5e8aacdaa3c15..598ba380028946 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs @@ -83,6 +83,10 @@ public enum ByValueMarshalKindSupport /// The provided is supported but does not change behavior from the default in this scenario. /// Unnecessary, + /// + /// The provided is supported but does not follow best practices. + /// + NotRecommended, } /// diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StaticPinnableManagedValueMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StaticPinnableManagedValueMarshaller.cs index 45ef61f85dbc58..4390d522099b09 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StaticPinnableManagedValueMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StaticPinnableManagedValueMarshaller.cs @@ -105,7 +105,7 @@ private IEnumerable GeneratePinningPath(TypePositionInfo info, public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) { - return ByValueMarshalKindSupportDescriptor.PinnedParameter.GetSupport(marshalKind, info, context, out diagnostic); + return ByValueMarshalKindSupportDescriptor.ArrayParameter.GetSupport(marshalKind, info, context, out diagnostic); } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs new file mode 100644 index 00000000000000..973b8fb782010d --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs @@ -0,0 +1,28 @@ + +// 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.Diagnostics; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using Microsoft.Interop.UnitTests; +using Xunit; +using VerifyComInterfaceGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier; + + + +namespace ComInterfaceGenerator.Unit.Tests +{ + public class BestPracticesMessagesTests + { + [Fact] + public void ArrayParameterWithNoAttributesGivesMessage() + { + // var source = ""; + + } + + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj index 08ca1a56fa43c8..beda4af3a72283 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj @@ -33,6 +33,7 @@ + diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj index 63256a99295555..f55883a3de833e 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj @@ -11,7 +11,7 @@ - + From ee1b3bb99ceaf36822a3a80a2cd0ee18eb96f0b4 Mon Sep 17 00:00:00 2001 From: Jackson Schuster Date: Tue, 22 Aug 2023 23:20:09 +0000 Subject: [PATCH 2/5] wip --- .../DiagnosticDescriptorProvider.cs | 1 + .../GeneratorDiagnostics.cs | 10 ++ .../gen/Common/Resources/Strings.resx | 18 ++- .../gen/Common/Resources/xlf/Strings.cs.xlf | 32 +++- .../gen/Common/Resources/xlf/Strings.de.xlf | 32 +++- .../gen/Common/Resources/xlf/Strings.es.xlf | 32 +++- .../gen/Common/Resources/xlf/Strings.fr.xlf | 32 +++- .../gen/Common/Resources/xlf/Strings.it.xlf | 32 +++- .../gen/Common/Resources/xlf/Strings.ja.xlf | 32 +++- .../gen/Common/Resources/xlf/Strings.ko.xlf | 32 +++- .../gen/Common/Resources/xlf/Strings.pl.xlf | 32 +++- .../Common/Resources/xlf/Strings.pt-BR.xlf | 32 +++- .../gen/Common/Resources/xlf/Strings.ru.xlf | 32 +++- .../gen/Common/Resources/xlf/Strings.tr.xlf | 32 +++- .../Common/Resources/xlf/Strings.zh-Hans.xlf | 32 +++- .../Common/Resources/xlf/Strings.zh-Hant.xlf | 32 +++- .../DiagnosticDescriptorProvider.cs | 1 + .../GeneratorDiagnostics.cs | 10 ++ .../IncrementalValuesProviderExtensions.cs | 2 +- .../ByValueContentsMarshalKindValidator.cs | 2 +- .../ByValueMarshalKindSupportDescriptor.cs | 30 ++-- .../BestPracticeMessagesTests.cs | 30 +++- .../CompileFails.cs | 138 +++++++++++++----- 23 files changed, 526 insertions(+), 132 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/DiagnosticDescriptorProvider.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/DiagnosticDescriptorProvider.cs index c676f27cb9f401..fab2d39182c8b7 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/DiagnosticDescriptorProvider.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/DiagnosticDescriptorProvider.cs @@ -26,6 +26,7 @@ internal sealed class DiagnosticDescriptorProvider : IDiagnosticDescriptorProvid GeneratorDiagnostic.NotSupported { NotSupportedDetails: not null, TypePositionInfo.IsManagedReturnPosition: false } => GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails, GeneratorDiagnostic.UnnecessaryData { TypePositionInfo.IsManagedReturnPosition: false } => GeneratorDiagnostics.UnnecessaryParameterMarshallingInfo, GeneratorDiagnostic.UnnecessaryData { TypePositionInfo.IsManagedReturnPosition: true } => GeneratorDiagnostics.UnnecessaryReturnMarshallingInfo, + GeneratorDiagnostic.NotRecommended => GeneratorDiagnostics.GeneratedComInterfaceUsageDoesNotFollowBestPractices, { IsFatal: false } => null, { TypePositionInfo.IsManagedReturnPosition: true } => GeneratorDiagnostics.ReturnTypeNotSupported, { TypePositionInfo.IsManagedReturnPosition: false } => GeneratorDiagnostics.ParameterTypeNotSupported, diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs index f0b98c3c535ac3..fd2132e826c15e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs @@ -485,6 +485,16 @@ public class Ids DiagnosticSeverity.Info, isEnabledByDefault: true); + /// + public static readonly DiagnosticDescriptor GeneratedComInterfaceUsageDoesNotFollowBestPractices = + new DiagnosticDescriptor( + Ids.NotRecommendedGeneratedComInterfaceUsage, + GetResourceString(nameof(SR.ComInterfaceUsageDoesNotFollowBestPracticesTitle)), + GetResourceString(nameof(SR.ComInterfaceUsageDoesNotFollowBestPracticesMessageWithDetails)), + 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 77f189684d3544..d970186aaeae85 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx @@ -875,7 +875,13 @@ [In] and [Out] attributes - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + + + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + + + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. 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. @@ -893,9 +899,15 @@ It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters. - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + + + The usage of 'LibraryImportAttribute' does not follow recommendations. + + + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} 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 2a15cc5e3f49b8..d6d9c42ac2e8c5 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 @@ -148,13 +148,13 @@ - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. @@ -457,6 +457,11 @@ This type will be treated as a struct in the native signature, not as a native HRESULT + + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + + The '[In]' attribute is not supported unless the '[Out]' attribute is also used. Blittable arrays cannot be marshalled as '[In]' only. Atribut [In] není podporován, pokud není použit také atribut [Out]. Blittable arrays nelze zařadit pouze jako [In]. @@ -477,6 +482,11 @@ Poskytnuté atributy „[In]“ a „[Out]“ u tohoto parametru se na tomto parametru nepodporují. + + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + + [In] and [Out] attributes atributy [In] a [Out] @@ -712,6 +722,16 @@ Neplatné použití atributu VirtualMethodIndexAttribute + + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + + + + The usage of 'LibraryImportAttribute' does not follow recommendations. + The usage of 'LibraryImportAttribute' does not follow recommendations. + + The element type of the 'ReadOnlySpan' returned by 'GetManagedValuesSource' must be the same as the element type returned by 'GetManagedValuesDestination'. Typ prvku ReadOnlySpan vrácený GetManagedValuesSource musí být stejný, jako typ prvku vrácený GetManagedValuesDestination. @@ -913,8 +933,8 @@ - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. 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 85de74504e4ae0..10db64b167a76b 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 @@ -148,13 +148,13 @@ - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. @@ -457,6 +457,11 @@ This type will be treated as a struct in the native signature, not as a native HRESULT + + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + + The '[In]' attribute is not supported unless the '[Out]' attribute is also used. Blittable arrays cannot be marshalled as '[In]' only. Das [In]-Attribut wird nur unterstützt, wenn auch das [Out]-Attribut verwendet wird. Blittable-Arrays können nicht nur als "[In]" gemarshallt werden. @@ -477,6 +482,11 @@ Die angegebenen Attribute \"[In]\" und \"[Out]\" für diesen Parameter werden für diesen Parameter nicht unterstützt. + + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + + [In] and [Out] attributes [In]- und [Out]-Attribute @@ -712,6 +722,16 @@ Ungültige Verwendung von "VirtualMethodIndexAttribute" + + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + + + + The usage of 'LibraryImportAttribute' does not follow recommendations. + The usage of 'LibraryImportAttribute' does not follow recommendations. + + The element type of the 'ReadOnlySpan' returned by 'GetManagedValuesSource' must be the same as the element type returned by 'GetManagedValuesDestination'. Der von \"GetManagedValuesSource\" zurückgegebene Elementtyp \"ReadOnlySpan\" muss mit dem Elementtyp identisch sein, der von \"GetManagedValuesDestination\" zurückgegeben wird. @@ -913,8 +933,8 @@ - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. 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 b8f615258f6afd..70bd4636f3cff5 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 @@ -148,13 +148,13 @@ - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. @@ -457,6 +457,11 @@ This type will be treated as a struct in the native signature, not as a native HRESULT + + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + + The '[In]' attribute is not supported unless the '[Out]' attribute is also used. Blittable arrays cannot be marshalled as '[In]' only. El atributo '[In]' no se admite a menos que también se use el atributo '[Out]'. Las matrices que se pueden transferir en bloque de bits no se pueden serializar solo como '[In]'. @@ -477,6 +482,11 @@ En este parámetro, los atributos “[In]” y “[Out]” proporcionados no se admiten. + + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + + [In] and [Out] attributes Atributos [In] y [Out] @@ -712,6 +722,16 @@ Uso de ”VirtualMethodIndexAttribute” no válido + + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + + + + The usage of 'LibraryImportAttribute' does not follow recommendations. + The usage of 'LibraryImportAttribute' does not follow recommendations. + + The element type of the 'ReadOnlySpan' returned by 'GetManagedValuesSource' must be the same as the element type returned by 'GetManagedValuesDestination'. El tipo de elemento del “ReadOnlySpan” devuelto por “GetManagedValuesSource” debe ser el mismo que el tipo de elemento devuelto por “GetManagedValuesDestination”. @@ -913,8 +933,8 @@ - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. 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 d5c2a0aef06b88..f745f7d0169940 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 @@ -148,13 +148,13 @@ - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. @@ -457,6 +457,11 @@ This type will be treated as a struct in the native signature, not as a native HRESULT + + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + + The '[In]' attribute is not supported unless the '[Out]' attribute is also used. Blittable arrays cannot be marshalled as '[In]' only. L’attribut '[In]' n’est pas pris en charge, sauf si l’attribut '[Out]' est également utilisé. Les tableaux blittables ne peuvent pas être marshalés en tant que « [In] » uniquement. @@ -477,6 +482,11 @@ Les attributs « [In] » et « [Out] » fournis sur ce paramètre ne sont pas pris en charge sur ce paramètre. + + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + + [In] and [Out] attributes Attributs [In] et [Out] @@ -712,6 +722,16 @@ Utilisation de « VirtualMethodIndexAttribute » non valide + + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + + + + The usage of 'LibraryImportAttribute' does not follow recommendations. + The usage of 'LibraryImportAttribute' does not follow recommendations. + + The element type of the 'ReadOnlySpan' returned by 'GetManagedValuesSource' must be the same as the element type returned by 'GetManagedValuesDestination'. Le type d’élément de « ReadOnlySpan » retourné par « GetManagedValuesSource » doit être identique au type d’élément retourné par « GetManagedValuesDestination ». @@ -913,8 +933,8 @@ - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. - L’attribut '[Out]' est uniquement pris en charge sur les paramètres de tableau. Envisagez d’utiliser des mots clés 'out' ou 'ref' pour rendre le paramètre mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + L’attribut '[Out]' est uniquement pris en charge sur les paramètres de tableau. Envisagez d’utiliser des mots clés 'out' ou 'ref' pour rendre le paramètre mutable. 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 35d79dac1fa795..ca37a8370b1c3a 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 @@ -148,13 +148,13 @@ - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. @@ -457,6 +457,11 @@ This type will be treated as a struct in the native signature, not as a native HRESULT + + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + + The '[In]' attribute is not supported unless the '[Out]' attribute is also used. Blittable arrays cannot be marshalled as '[In]' only. L'attributo '[In]' non è supportato a meno che non venga usato anche l'attributo '[Out]'. Le matrici copiabili da BLT non possono essere sottoposte a marshalling solo come '[In]'. @@ -477,6 +482,11 @@ Gli attributi '[In]' e '[Out]' specificati per questo parametro non sono supportati in questo parametro. + + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + + [In] and [Out] attributes Attributi [In] e [Out] @@ -712,6 +722,16 @@ Utilizzo di 'VirtualMethodIndexAttribute' non valido + + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + + + + The usage of 'LibraryImportAttribute' does not follow recommendations. + The usage of 'LibraryImportAttribute' does not follow recommendations. + + The element type of the 'ReadOnlySpan' returned by 'GetManagedValuesSource' must be the same as the element type returned by 'GetManagedValuesDestination'. Il tipo di elemento di 'ReadOnlySpan' restituito da 'GetManagedValuesSource' deve essere uguale al tipo di elemento restituito da 'GetManagedValuesDestination'. @@ -913,8 +933,8 @@ - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. - L'attributo '[Out]' è supportato solo nei parametri di matrice. Provare a usare le parole chiave 'out' o 'ref' per rendere modificabile il parametro. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + L'attributo '[Out]' è supportato solo nei parametri di matrice. Provare a usare le parole chiave 'out' o 'ref' per rendere modificabile il parametro. 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 12c47e3084a678..c071a27f1ea7c5 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 @@ -148,13 +148,13 @@ - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. @@ -457,6 +457,11 @@ This type will be treated as a struct in the native signature, not as a native HRESULT + + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + + The '[In]' attribute is not supported unless the '[Out]' attribute is also used. Blittable arrays cannot be marshalled as '[In]' only. '[In]'属性は、'[Out]'属性も使用しない限りサポートされません。Blittable 配列は、'[In]'としてのみマーシャリングできません。 @@ -477,6 +482,11 @@ このパラメーターに指定された '[In]' 属性と '[Out]' 属性は、このパラメーターではサポートされていません。 + + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + + [In] and [Out] attributes 属性の[In]と[Out] @@ -712,6 +722,16 @@ 'VirtualMethodIndexAttribute' の使用法が無効です + + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + + + + The usage of 'LibraryImportAttribute' does not follow recommendations. + The usage of 'LibraryImportAttribute' does not follow recommendations. + + The element type of the 'ReadOnlySpan' returned by 'GetManagedValuesSource' must be the same as the element type returned by 'GetManagedValuesDestination'. 'GetManagedValuesSource' によって返される 'ReadOnlySpan' の要素型は、'GetManagedValuesDestination' によって返される要素型と同じである必要があります。 @@ -913,8 +933,8 @@ - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. 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 0bf758a06ab444..b08e23611687cd 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 @@ -148,13 +148,13 @@ - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. @@ -457,6 +457,11 @@ This type will be treated as a struct in the native signature, not as a native HRESULT + + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + + The '[In]' attribute is not supported unless the '[Out]' attribute is also used. Blittable arrays cannot be marshalled as '[In]' only. '[Out]' 특성도 사용되지 않는 한 '[In]' 특성은 지원되지 않습니다. Blittable 배열은 '[In]'으로만 마샬링할 수 없습니다. @@ -477,6 +482,11 @@ 이 매개 변수에 제공된 '[In]' 및 '[Out]' 특성은 이 매개 변수에서 지원되지 않습니다. + + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + + [In] and [Out] attributes [In] 및 [Out] 속성 @@ -712,6 +722,16 @@ 잘못된 'VirtualMethodIndexAttribute' 사용 + + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + + + + The usage of 'LibraryImportAttribute' does not follow recommendations. + The usage of 'LibraryImportAttribute' does not follow recommendations. + + The element type of the 'ReadOnlySpan' returned by 'GetManagedValuesSource' must be the same as the element type returned by 'GetManagedValuesDestination'. 'GetManagedValuesSource'에서 반환된 'ReadOnlySpan'의 요소 형식은 'GetManagedValuesDestination'에서 반환된 요소 형식과 동일해야 합니다. @@ -913,8 +933,8 @@ - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. 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 a01b85625b88e9..f6125068ae6c2a 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 @@ -148,13 +148,13 @@ - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. @@ -457,6 +457,11 @@ This type will be treated as a struct in the native signature, not as a native HRESULT + + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + + The '[In]' attribute is not supported unless the '[Out]' attribute is also used. Blittable arrays cannot be marshalled as '[In]' only. Atrybut „[In]” nie jest obsługiwany, chyba że używany jest również atrybut „[Out]”. Tablice kopiowalne nie mogą być kierowane tylko jako „[In]”. @@ -477,6 +482,11 @@ Podane atrybuty „[In]” i „[Out]” w tym parametrze nie są obsługiwane w tym parametrze. + + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + + [In] and [Out] attributes Atrybuty [In] i [Out] @@ -712,6 +722,16 @@ Nieprawidłowe użycie atrybutu „VirtualMethodIndexAttribute” + + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + + + + The usage of 'LibraryImportAttribute' does not follow recommendations. + The usage of 'LibraryImportAttribute' does not follow recommendations. + + The element type of the 'ReadOnlySpan' returned by 'GetManagedValuesSource' must be the same as the element type returned by 'GetManagedValuesDestination'. Typ elementu „ReadOnlySpan” zwracany przez element „GetManagedValuesSource” musi być taki sam jak typ elementu zwracany przez element „GetManagedValuesDestination”. @@ -913,8 +933,8 @@ - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. - Atrybut „[Out]” jest obsługiwany tylko w przypadku parametrów tablicy. Rozważ użycie słów kluczowych „out” lub „ref”, aby umożliwić modyfikowanie parametru. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + Atrybut „[Out]” jest obsługiwany tylko w przypadku parametrów tablicy. Rozważ użycie słów kluczowych „out” lub „ref”, aby umożliwić modyfikowanie parametru. 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 87ef939e0b1211..85222b527258d5 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 @@ -148,13 +148,13 @@ - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. @@ -457,6 +457,11 @@ This type will be treated as a struct in the native signature, not as a native HRESULT + + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + + The '[In]' attribute is not supported unless the '[Out]' attribute is also used. Blittable arrays cannot be marshalled as '[In]' only. O atributo '[In]' não é suportado, a menos que o atributo '[Out]' também seja usado. Matrizes Blittable não podem ser empacotadas apenas como '[In]'. @@ -477,6 +482,11 @@ Os atributos '[In]' e '[Out]' neste parâmetro não têm suporte neste parâmetro. + + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + + [In] and [Out] attributes Atributos [In] e [Out] @@ -712,6 +722,16 @@ Uso de 'VirtualMethodIndexAttribute' inválido + + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + + + + The usage of 'LibraryImportAttribute' does not follow recommendations. + The usage of 'LibraryImportAttribute' does not follow recommendations. + + The element type of the 'ReadOnlySpan' returned by 'GetManagedValuesSource' must be the same as the element type returned by 'GetManagedValuesDestination'. O tipo de elemento de 'ReadOnlySpan' retornado por 'GetManagedValuesSource' deve ser igual ao tipo de elemento retornado por 'GetManagedValuesDestination'. @@ -913,8 +933,8 @@ - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. 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 640c7cc028a4d7..5e564cb4cb0ffe 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 @@ -148,13 +148,13 @@ - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. @@ -457,6 +457,11 @@ This type will be treated as a struct in the native signature, not as a native HRESULT + + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + + The '[In]' attribute is not supported unless the '[Out]' attribute is also used. Blittable arrays cannot be marshalled as '[In]' only. Атрибут "[In]" не поддерживается, если также не используется атрибут "[Out]". Преобразуемые массивы нельзя сортировать только как "[In]". @@ -477,6 +482,11 @@ Указанные атрибуты \"[In]\" и \"[Out]\" для этого параметра не поддерживаются. + + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + + [In] and [Out] attributes Атрибуты [In] и [Out] @@ -712,6 +722,16 @@ Недопустимое использование VirtualMethodIndexAttribute + + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + + + + The usage of 'LibraryImportAttribute' does not follow recommendations. + The usage of 'LibraryImportAttribute' does not follow recommendations. + + The element type of the 'ReadOnlySpan' returned by 'GetManagedValuesSource' must be the same as the element type returned by 'GetManagedValuesDestination'. Тип элемента \"ReadOnlySpan\", возвращенный методом \"GetManagedValuesSource\", должен совпадать с типом элемента, возвращаемым методом \"GetManagedValuesDestination\". @@ -913,8 +933,8 @@ - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. - Атрибут "[Out]" поддерживается только для параметров массива. Рассмотрите возможность использования ключевых слов "out" или "ref", чтобы сделать параметр изменяемым. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + Атрибут "[Out]" поддерживается только для параметров массива. Рассмотрите возможность использования ключевых слов "out" или "ref", чтобы сделать параметр изменяемым. 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 139b29340add96..defba8092b3f8a 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 @@ -148,13 +148,13 @@ - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. @@ -457,6 +457,11 @@ This type will be treated as a struct in the native signature, not as a native HRESULT + + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + + The '[In]' attribute is not supported unless the '[Out]' attribute is also used. Blittable arrays cannot be marshalled as '[In]' only. '[Out]' özniteliği de kullanılmadığı sürece '[In]' özniteliği desteklenmez. Blittable dizileri yalnızca '[In]' olarak hazırlanamaz. @@ -477,6 +482,11 @@ Bu parametrede sağlanan '[In]' ve '[Out]' öznitelikleri bu parametrede desteklenmiyor. + + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + + [In] and [Out] attributes [In] ve [Out] öznitelikleri @@ -712,6 +722,16 @@ Geçersiz 'VirtualMethodIndexAttribute' kullanımı + + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + + + + The usage of 'LibraryImportAttribute' does not follow recommendations. + The usage of 'LibraryImportAttribute' does not follow recommendations. + + The element type of the 'ReadOnlySpan' returned by 'GetManagedValuesSource' must be the same as the element type returned by 'GetManagedValuesDestination'. 'GetManagedValuesSource' tarafından döndürülen 'ReadOnlySpan' öğe türü, 'GetManagedValuesDestination' tarafından döndürülen öğe türüyle aynı olmalıdır. @@ -913,8 +933,8 @@ - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. - '[Out]' özniteliği yalnızca dizi parametrelerinde desteklenir. Parametreyi değiştirilebilir yapmak için 'out' veya 'ref' anahtar sözcükleri kullanmayı düşünün. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + '[Out]' özniteliği yalnızca dizi parametrelerinde desteklenir. Parametreyi değiştirilebilir yapmak için 'out' veya 'ref' anahtar sözcükleri kullanmayı düşünün. 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 170703c0f6916b..82436e835396e1 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 @@ -148,13 +148,13 @@ - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. @@ -457,6 +457,11 @@ This type will be treated as a struct in the native signature, not as a native HRESULT + + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + + The '[In]' attribute is not supported unless the '[Out]' attribute is also used. Blittable arrays cannot be marshalled as '[In]' only. 不支持“[In]”属性,除非也使用“[Out]”属性。不能仅将 Blittable 数组封送为“[In]”。 @@ -477,6 +482,11 @@ 此参数上提供的 “[In]” 和 “[Out]” 属性在此参数上不受支持。 + + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + + [In] and [Out] attributes [In] 和 [Out] 属性 @@ -712,6 +722,16 @@ “VirtualMethodIndexAttribute” 使用情况无效 + + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + + + + The usage of 'LibraryImportAttribute' does not follow recommendations. + The usage of 'LibraryImportAttribute' does not follow recommendations. + + The element type of the 'ReadOnlySpan' returned by 'GetManagedValuesSource' must be the same as the element type returned by 'GetManagedValuesDestination'. “GetManagedValuesSource” 返回的 “ReadOnlySpan” 的元素类型必须与 “GetManagedValuesDestination” 返回的元素类型相同。 @@ -913,8 +933,8 @@ - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. 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 8f782b0c2d68da..0d6dfb9f802a46 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 @@ -148,13 +148,13 @@ - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. - The 'GeneratedComInterfaceAttribute' usage does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. @@ -457,6 +457,11 @@ This type will be treated as a struct in the native signature, not as a native HRESULT + + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + The '[In]' attribute is only supported on array parameters. By-value parameters are considered read-only by default. + + The '[In]' attribute is not supported unless the '[Out]' attribute is also used. Blittable arrays cannot be marshalled as '[In]' only. 除非也使用 '[Out]' 屬性,否則不支援 '[In]' 屬性。無法只將 Blittable 陣列整理為 '[In]'。 @@ -477,6 +482,11 @@ 此參數不支援在此參數上提供的 '[In]' 和 '[Out]' 屬性。 + + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + The '[In]' and '[Out]' attributes are only supported on array parameters. Consider using the 'ref' keyword to make the parameter mutable. + + [In] and [Out] attributes [In] 與 [Out] 屬性 @@ -712,6 +722,16 @@ 'VirtualMethodIndexAttribute' 使用方式無效 + + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + The usage of 'LibraryImportAttribute' does not follow recommendations. {0} + + + + The usage of 'LibraryImportAttribute' does not follow recommendations. + The usage of 'LibraryImportAttribute' does not follow recommendations. + + The element type of the 'ReadOnlySpan' returned by 'GetManagedValuesSource' must be the same as the element type returned by 'GetManagedValuesDestination'. 'GetManagedValuesSource' 傳回的 'ReadOnlySpan' 元素類型必須與 'GetManagedValuesDestination' 傳回的元素類型相同。 @@ -913,8 +933,8 @@ - The `[Out]` attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. - 只有陣列參數才支援 '[Out]' 屬性。請考慮使用 'out' 或 'ref' 關鍵字將參數設為可變。 + The '[Out]' attribute is only supported on array parameters. Consider using 'out' or 'ref' keywords to make the parameter mutable. + 只有陣列參數才支援 '[Out]' 屬性。請考慮使用 'out' 或 'ref' 關鍵字將參數設為可變。 diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/DiagnosticDescriptorProvider.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/DiagnosticDescriptorProvider.cs index 2bef64490f9a4e..eb9a0237307bc3 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/DiagnosticDescriptorProvider.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/DiagnosticDescriptorProvider.cs @@ -24,6 +24,7 @@ internal sealed class DiagnosticDescriptorProvider : IDiagnosticDescriptorProvid GeneratorDiagnostic.NotSupported { NotSupportedDetails: not null, TypePositionInfo.IsManagedReturnPosition: false } => GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails, GeneratorDiagnostic.UnnecessaryData { TypePositionInfo.IsManagedReturnPosition: false } => GeneratorDiagnostics.UnnecessaryParameterMarshallingInfo, GeneratorDiagnostic.UnnecessaryData { TypePositionInfo.IsManagedReturnPosition: true } => GeneratorDiagnostics.UnnecessaryReturnMarshallingInfo, + GeneratorDiagnostic.NotRecommended => GeneratorDiagnostics.LibraryImportUsageDoesNotFollowBestPractices, { IsFatal: false } => null, { TypePositionInfo.IsManagedReturnPosition: true } => GeneratorDiagnostics.ReturnTypeNotSupported, { TypePositionInfo.IsManagedReturnPosition: false } => GeneratorDiagnostics.ParameterTypeNotSupported, diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs index 2af2abadcdd607..f5fd78d48e587c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs @@ -254,6 +254,16 @@ public class Ids DiagnosticSeverity.Warning, isEnabledByDefault: true); + /// + public static readonly DiagnosticDescriptor LibraryImportUsageDoesNotFollowBestPractices = + new DiagnosticDescriptor( + Ids.NotRecommendedGeneratedComInterfaceUsage, + GetResourceString(nameof(SR.LibraryImportUsageDoesNotFollowBestPracticesTitle)), + GetResourceString(nameof(SR.LibraryImportUsageDoesNotFollowBestPracticesMessageWithDetails)), + Category, + DiagnosticSeverity.Info, + isEnabledByDefault: true); + /// /// Report diagnostic for invalid configuration for string marshalling. /// diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalValuesProviderExtensions.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalValuesProviderExtensions.cs index 123d649c913cd5..5455510ac356c0 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalValuesProviderExtensions.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalValuesProviderExtensions.cs @@ -47,7 +47,7 @@ public static IncrementalValuesProvider SelectNormalized(this Incr return provider.Select((node, ct) => node.NormalizeWhitespace()); } - public static (IncrementalValuesProvider, IncrementalValuesProvider) Split(this IncrementalValuesProvider<(T, T2)> provider) + public static (IncrementalValuesProvider, IncrementalValuesProvider) Split(this IncrementalValuesProvider<(T, T2)> provider) { return (provider.Select(static (data, ct) => data.Item1), provider.Select(static (data, ct) => data.Item2)); } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs index f96da7cf28c513..dd7a40fb8c90e2 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs @@ -27,7 +27,7 @@ public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) private static ResolvedGenerator ValidateByValueMarshalKind(TypePositionInfo info, StubCodeContext context, ResolvedGenerator generator) { - if (generator.Generator is Forwarder || info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Default) + if (generator.Generator is Forwarder) { // Forwarder allows everything since it just forwards to a P/Invoke. // The Default marshal kind is always valid. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs index 052ef87d9c608c..0469da175069c1 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Immutable; +using System.Diagnostics; namespace Microsoft.Interop { @@ -33,7 +34,7 @@ public ByValueMarshalKindSupport GetSupport(TypePositionInfo info, StubCodeConte NotSupportedDetails = details }, _ => throw new UnreachableException() - }; + }; return Support; } } @@ -52,9 +53,9 @@ public record ByValueMarshalKindSupportDescriptor( /// public static readonly ByValueMarshalKindSupportDescriptor Default = new ByValueMarshalKindSupportDescriptor( DefaultSupport: new(ByValueMarshalKindSupport.Supported, null), - InSupport: new(ByValueMarshalKindSupport.NotSupported, SR.OutAttributeNotSupportedOnByValueParameters), + InSupport: new(ByValueMarshalKindSupport.NotSupported, SR.InAttributeNotSupportedOnByValueParameters), OutSupport: new(ByValueMarshalKindSupport.NotSupported, SR.OutAttributeNotSupportedOnByValueParameters), - InOutSupport: new(ByValueMarshalKindSupport.NotSupported, SR.OutAttributeNotSupportedOnByValueParameters)); + InOutSupport: new(ByValueMarshalKindSupport.NotSupported, SR.InOutAttributeNotSupportedOnByValueParameters)); /// /// A default for by value array parameters. Default is allowed, but Not Recommended. [In], [Out], and [In, Out] are allowed @@ -70,18 +71,25 @@ public record ByValueMarshalKindSupportDescriptor( /// public ByValueMarshalKindSupport GetSupport(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) { - if (info.IsByRef && marshalKind != ByValueContentsMarshalKind.Default) + if (info.IsByRef) { - diagnostic = new GeneratorDiagnostic.NotSupported(info, context) + // ByRef with ByValue attributes is not allowed + if (marshalKind != ByValueContentsMarshalKind.Default) { - NotSupportedDetails = SR.InOutAttributeByRefNotSupported - }; - return ByValueMarshalKindSupport.NotSupported; + diagnostic = new GeneratorDiagnostic.NotSupported(info, context) + { + NotSupportedDetails = SR.InOutAttributeByRefNotSupported + }; + return ByValueMarshalKindSupport.NotSupported; + } + // ByRef with no ByValue attributes is supported + diagnostic = null; + return ByValueMarshalKindSupport.Supported; } - // Do return types ever get here? - // Return types should never have In or Out attributes - if (info.ManagedIndex < 0 && marshalKind is ByValueContentsMarshalKind.Default) + // Return can never have In or Out attributes, so can assume valid ByValue attributes + if (info.ManagedIndex < 0) { + Debug.Assert(marshalKind is ByValueContentsMarshalKind.Default); diagnostic = null; return ByValueMarshalKindSupport.Supported; } diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs index 973b8fb782010d..46db4182f2d96e 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs @@ -7,6 +7,8 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.Interop; using Microsoft.Interop.UnitTests; using Xunit; using VerifyComInterfaceGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier; @@ -18,11 +20,33 @@ namespace ComInterfaceGenerator.Unit.Tests public class BestPracticesMessagesTests { [Fact] - public void ArrayParameterWithNoAttributesGivesMessage() + public async Task ArrayParameterWithNoAttributesGivesMessage() { - // var source = ""; + var source = $$""" + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; - } + [GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)] + [Guid("a4a20815-f1f2-4fa6-ada7-ecb05ac60d30")] + internal partial interface IFoo + { + void BlittableArray([MarshalUsing(CountElementName = nameof(size))] int[] {|#0:param|}, int size); + void BlittableOutArray([MarshalUsing(CountElementName = nameof(size))] out int[] param, int size); + void MaybeBlittableArray([MarshalUsing(CountElementName = nameof(size))] char[] {|#1:param|}, int size); + void NonBlittableArray([MarshalUsing(CountElementName = nameof(size))] IntStruct[] {|#2:param|}, int size); + } + """ + CodeSnippets.IntStructAndMarshaller; + var diagnostic = new DiagnosticResult(GeneratorDiagnostics.GeneratedComInterfaceUsageDoesNotFollowBestPractices) + .WithArguments(SR.PreferExplicitInOutAttributesOnArrays); + VerifyComInterfaceGenerator.Test test = new(referenceAncillaryInterop: false) + { + TestCode = source, + TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck, + CompilerDiagnostics = CompilerDiagnostics.Suggestions, + }; + test.ExpectedDiagnostics.AddRange([diagnostic.WithLocation(0), diagnostic.WithLocation(1), diagnostic.WithLocation(2)]); + await test.RunAsync(); + } } } 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 2e4d25da3837e5..21bd970f6cf708 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 @@ -550,54 +550,57 @@ public static IEnumerable ByValueMarshalAttributeOnValueTypes() const string outAttribute = "[{|#2:OutAttribute|}]"; const string paramName = "p"; string paramNameWithLocation = $$"""{|#0:{{paramName}}|}"""; - var inAttributeIsDefaultDiagnostic = new DiagnosticResult(GeneratorDiagnostics.UnnecessaryParameterMarshallingInfo) - .WithLocation(0) + var diagnostic = new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails); + var outAttributeNotSupported = diagnostic + .WithLocation(2) + .WithArguments(SR.OutAttributeNotSupportedOnByValueParameters, paramName); + var inAttributeIsNotSupported = diagnostic .WithLocation(1) - .WithArguments(SR.InOutAttributes, paramName, SR.InAttributeOnlyIsDefault); + .WithArguments(SR.InAttributeNotSupportedOnByValueParameters, paramName); + var inOutAttributeNotSupported = diagnostic + .WithLocation(1) + .WithLocation(2) + .WithArguments(SR.InOutAttributeNotSupportedOnByValueParameters, paramName); // [In] is default for all non-pinned marshalled types yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute, "int", paramNameWithLocation), new DiagnosticResult[] { - inAttributeIsDefaultDiagnostic } }; + inAttributeIsNotSupported } }; yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute, "byte", paramNameWithLocation), new DiagnosticResult[] { - inAttributeIsDefaultDiagnostic } }; + inAttributeIsNotSupported } }; yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + "[MarshalAs(UnmanagedType.U4)]", "bool", paramNameWithLocation), new DiagnosticResult[] { - inAttributeIsDefaultDiagnostic } }; + inAttributeIsNotSupported } }; yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + "[MarshalAs(UnmanagedType.U2)]", "char", paramNameWithLocation), new DiagnosticResult[] { - inAttributeIsDefaultDiagnostic } }; + inAttributeIsNotSupported } }; - // [Out] is not allowed on value types passed by value - there is no indirection for the callee to make visible modifications. - var outAttributeNotSupportedOnValueParameters = new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) - .WithLocation(0) - .WithArguments(SR.OutAttributeNotSupportedOnByValueParameters, paramName); yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(outAttribute, "int", paramNameWithLocation), new DiagnosticResult[] { - outAttributeNotSupportedOnValueParameters } }; + outAttributeNotSupported } }; yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(outAttribute, "IntStruct", paramNameWithLocation) + CodeSnippets.IntStructAndMarshaller, new DiagnosticResult[] { - outAttributeNotSupportedOnValueParameters + outAttributeNotSupported } }; yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(outAttribute + "[MarshalAs(UnmanagedType.U4)]", "bool", paramNameWithLocation), new DiagnosticResult[] { - outAttributeNotSupportedOnValueParameters + outAttributeNotSupported } }; yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(outAttribute, "[MarshalAs(UnmanagedType.U2)] char", paramNameWithLocation), new DiagnosticResult[] { - outAttributeNotSupportedOnValueParameters + outAttributeNotSupported } }; // [In,Out] should only warn for Out attribute yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute+outAttribute, "int", paramNameWithLocation), new DiagnosticResult[] { - outAttributeNotSupportedOnValueParameters } }; + inOutAttributeNotSupported } }; yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute+outAttribute, "IntStruct", paramNameWithLocation) + CodeSnippets.IntStructAndMarshaller, new DiagnosticResult[] { - outAttributeNotSupportedOnValueParameters + inOutAttributeNotSupported } }; yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute + "[MarshalAs(UnmanagedType.U4)]", "bool", paramNameWithLocation), new DiagnosticResult[] { - outAttributeNotSupportedOnValueParameters + inOutAttributeNotSupported } }; yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute, "[MarshalAs(UnmanagedType.U2)] char", paramNameWithLocation), new DiagnosticResult[] { - outAttributeNotSupportedOnValueParameters + inOutAttributeNotSupported } }; // Any ref keyword is okay for value types @@ -738,21 +741,21 @@ public static IEnumerable ByValueMarshalAttributeOnPinnedMarshalledTyp const string paramName = "p"; string paramNameWithLocation = $$"""{|#0:{{paramName}}|}"""; const string constElementCount = @"[MarshalUsing(ConstantElementCount = 10)]"; - var inAttributeIsDefaultDiagnostic = new DiagnosticResult(GeneratorDiagnostics.UnnecessaryParameterMarshallingInfo) - .WithLocation(0) - .WithLocation(1) - .WithArguments(SR.InOutAttributes, paramName, SR.InAttributeOnlyIsDefault); - yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + constElementCount, "int[]", paramNameWithLocation), new DiagnosticResult[] { - inAttributeIsDefaultDiagnostic - }}; + // [In] int[] + yield return new object[] { + ID(), + codeSnippets.ByValueMarshallingOfType(inAttribute + constElementCount, "int[]", paramNameWithLocation), + new DiagnosticResult[] { } + }; + // [In] char[] blittable yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + constElementCount, "char[]", paramNameWithLocation, (StringMarshalling.Utf16, null)), - new DiagnosticResult[] { inAttributeIsDefaultDiagnostic } + new DiagnosticResult[] { } }; - // bools that are marshalled into a new array are in by default + // [In] bool[] (not blittable) yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType( @@ -760,43 +763,94 @@ public static IEnumerable ByValueMarshalAttributeOnPinnedMarshalledTyp "bool[]", paramNameWithLocation, (StringMarshalling.Utf16, null)), - new DiagnosticResult[] { inAttributeIsDefaultDiagnostic } + new DiagnosticResult[] { } }; - // Overriding marshalling with a custom marshaller makes it not pinned + // [In] int[] with custom marshaller (not blittable) yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute, "[MarshalUsing(typeof(IntMarshaller), ElementIndirectionDepth = 1), MarshalUsing(ConstantElementCount = 10)]int[]", paramNameWithLocation) + CodeSnippets.IntMarshaller, - new DiagnosticResult[] { inAttributeIsDefaultDiagnostic } + new DiagnosticResult[] { } }; - + // [In, Out] int[] (blittable pinned) yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute + constElementCount, "int[]", paramNameWithLocation), new DiagnosticResult[] { } }; + // [In, Out] char[] (utf16 blittable pinned) yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute + constElementCount, "char[]", paramNameWithLocation, (StringMarshalling.Utf16, null)), new DiagnosticResult[] { } }; - + // [Out] int[] yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(outAttribute + constElementCount, "int[]", paramNameWithLocation), new DiagnosticResult[] { } }; - + // [Out] char[] yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(outAttribute + constElementCount, "char[]", paramNameWithLocation, (StringMarshalling.Utf16, null)), new DiagnosticResult[] { } }; + + + // Without Attributes should provide info Diagnotic + var preferExplicitAttributesDiagnostic = new DiagnosticResult(GeneratorDiagnostics.GeneratedComInterfaceUsageDoesNotFollowBestPractices) + .WithLocation(0) + .WithArguments(SR.PreferExplicitInOutAttributesOnArrays); + + yield return new object[] { + ID(), + codeSnippets.ByValueMarshallingOfType(constElementCount, "int[]", paramNameWithLocation), + new DiagnosticResult[] { preferExplicitAttributesDiagnostic } + }; + yield return new object[] { + ID(), + codeSnippets.ByValueMarshallingOfType(constElementCount, "char[]", paramNameWithLocation, (StringMarshalling.Utf16, null)), + new DiagnosticResult[] { preferExplicitAttributesDiagnostic } + }; + yield return new object[] { + ID(), + codeSnippets.ByValueMarshallingOfType( + inAttribute + "[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeConst = 10)]", + "bool[]", + paramNameWithLocation, + (StringMarshalling.Utf16, null)), + new DiagnosticResult[] { preferExplicitAttributesDiagnostic } + }; + yield return new object[] { + ID(), + codeSnippets.ByValueMarshallingOfType("", "[MarshalUsing(typeof(IntMarshaller), ElementIndirectionDepth = 1), MarshalUsing(ConstantElementCount = 10)]int[]", paramNameWithLocation) + CodeSnippets.IntMarshaller, + new DiagnosticResult[] { preferExplicitAttributesDiagnostic } + }; + yield return new object[] { + ID(), + codeSnippets.ByValueMarshallingOfType(constElementCount, "int[]", paramNameWithLocation), + new DiagnosticResult[] { preferExplicitAttributesDiagnostic } + }; + yield return new object[] { + ID(), + codeSnippets.ByValueMarshallingOfType(constElementCount, "char[]", paramNameWithLocation, (StringMarshalling.Utf16, null)), + new DiagnosticResult[] { preferExplicitAttributesDiagnostic } + }; + yield return new object[] { + ID(), + codeSnippets.ByValueMarshallingOfType(constElementCount, "int[]", paramNameWithLocation), + new DiagnosticResult[] { preferExplicitAttributesDiagnostic } + }; + yield return new object[] { + ID(), + codeSnippets.ByValueMarshallingOfType(constElementCount, "char[]", paramNameWithLocation, (StringMarshalling.Utf16, null)), + new DiagnosticResult[] { preferExplicitAttributesDiagnostic } + }; } [Theory] [MemberData(nameof(ByValueMarshalAttributeOnValueTypes))] [MemberData(nameof(ByValueMarshalAttributeOnReferenceTypes))] - [MemberData(nameof(ByValueMarshalAttributeOnPinnedMarshalledTypes))] public async Task VerifyByValueMarshallingAttributeUsage(string id, string source, DiagnosticResult[] diagnostics) { _ = id; @@ -809,6 +863,20 @@ public async Task VerifyByValueMarshallingAttributeUsage(string id, string sourc await test.RunAsync(); } + [Theory] + [MemberData(nameof(ByValueMarshalAttributeOnPinnedMarshalledTypes))] + public async Task VerifyByValueMarshallingAttributeUsageInfoMessages(string id, string source, DiagnosticResult[] diagnostics) + { + _ = id; + VerifyComInterfaceGenerator.Test test = new(referenceAncillaryInterop: false) + { + TestCode = source, + TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck, + }; + test.ExpectedDiagnostics.AddRange(diagnostics); + await test.RunAsync(); + } + [Fact] public async Task VerifyNonPartialInterfaceWarns() { From b686622c9eeb772fe70f499de4f8216bdd4de21b Mon Sep 17 00:00:00 2001 From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:41:05 -0700 Subject: [PATCH 3/5] Added tests --- .../gen/Common/Resources/Strings.resx | 56 +-- .../gen/Common/Resources/xlf/Strings.cs.xlf | 4 +- .../gen/Common/Resources/xlf/Strings.de.xlf | 4 +- .../gen/Common/Resources/xlf/Strings.es.xlf | 4 +- .../gen/Common/Resources/xlf/Strings.fr.xlf | 4 +- .../gen/Common/Resources/xlf/Strings.it.xlf | 4 +- .../gen/Common/Resources/xlf/Strings.ja.xlf | 4 +- .../gen/Common/Resources/xlf/Strings.ko.xlf | 4 +- .../gen/Common/Resources/xlf/Strings.pl.xlf | 4 +- .../Common/Resources/xlf/Strings.pt-BR.xlf | 4 +- .../gen/Common/Resources/xlf/Strings.ru.xlf | 4 +- .../gen/Common/Resources/xlf/Strings.tr.xlf | 4 +- .../Common/Resources/xlf/Strings.zh-Hans.xlf | 4 +- .../Common/Resources/xlf/Strings.zh-Hant.xlf | 4 +- .../StaticPinnableManagedValueMarshaller.cs | 2 +- .../BestPracticeMessagesTests.cs | 8 +- .../ByValueContentsMarshalling.cs | 301 +++++++++++++++ .../CodeSnippets.cs | 45 +++ .../CompileFails.cs | 351 +----------------- .../tests/Common/TestUtils.cs | 26 +- .../SharedTypes/ComInterfaces/IIntArray.cs | 45 ++- .../IStatelessCollectionAllShapes.cs | 4 +- 22 files changed, 471 insertions(+), 419 deletions(-) create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ByValueContentsMarshalling.cs 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 d970186aaeae85..2da298e8a7b0df 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx +++ b/src/libraries/System.Runtime.InteropServices/gen/Common/Resources/Strings.resx @@ -1,17 +1,17 @@  - @@ -902,7 +902,7 @@ The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} The usage of 'LibraryImportAttribute' does not follow recommendations. 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 d6d9c42ac2e8c5..48a9bc03b73a63 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 @@ -148,8 +148,8 @@ - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} 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 10db64b167a76b..3135aa3bbe7eaa 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 @@ -148,8 +148,8 @@ - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} 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 70bd4636f3cff5..f0e4701f345ccf 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 @@ -148,8 +148,8 @@ - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} 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 f745f7d0169940..228abb0f43b9c8 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 @@ -148,8 +148,8 @@ - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} 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 ca37a8370b1c3a..58c83094b063bc 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 @@ -148,8 +148,8 @@ - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} 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 c071a27f1ea7c5..331eb28eaa414d 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 @@ -148,8 +148,8 @@ - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} 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 b08e23611687cd..aedf84c829c061 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 @@ -148,8 +148,8 @@ - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} 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 f6125068ae6c2a..f051d95f3b9c9e 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 @@ -148,8 +148,8 @@ - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} 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 85222b527258d5..c1bc60315bc05c 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 @@ -148,8 +148,8 @@ - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} 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 5e564cb4cb0ffe..891ef9d077eb61 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 @@ -148,8 +148,8 @@ - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} 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 defba8092b3f8a..6748b1305030b9 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 @@ -148,8 +148,8 @@ - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} 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 82436e835396e1..de0d085a227a7e 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 @@ -148,8 +148,8 @@ - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} 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 0d6dfb9f802a46..408df3131a3be5 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 @@ -148,8 +148,8 @@ - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} - The usage of'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} + The usage of 'GeneratedComInterfaceAttribute' does not follow recommendations. {0} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StaticPinnableManagedValueMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StaticPinnableManagedValueMarshaller.cs index 4390d522099b09..039d78ed350068 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StaticPinnableManagedValueMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StaticPinnableManagedValueMarshaller.cs @@ -105,7 +105,7 @@ private IEnumerable GeneratePinningPath(TypePositionInfo info, public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) { - return ByValueMarshalKindSupportDescriptor.ArrayParameter.GetSupport(marshalKind, info, context, out diagnostic); + return _innerMarshallingGenerator.SupportsByValueMarshalKind(marshalKind, info, context, out diagnostic); } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs index 46db4182f2d96e..a8a26b4547732a 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs @@ -3,18 +3,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Runtime.CompilerServices; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Testing; using Microsoft.Interop; -using Microsoft.Interop.UnitTests; using Xunit; using VerifyComInterfaceGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier; - namespace ComInterfaceGenerator.Unit.Tests { public class BestPracticesMessagesTests @@ -43,8 +38,9 @@ internal partial interface IFoo { TestCode = source, TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck, - CompilerDiagnostics = CompilerDiagnostics.Suggestions, + CompilerDiagnostics = CompilerDiagnostics.All, }; + test.DisabledDiagnostics.Remove(GeneratorDiagnostics.Ids.NotRecommendedGeneratedComInterfaceUsage); test.ExpectedDiagnostics.AddRange([diagnostic.WithLocation(0), diagnostic.WithLocation(1), diagnostic.WithLocation(2)]); await test.RunAsync(); } diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ByValueContentsMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ByValueContentsMarshalling.cs new file mode 100644 index 00000000000000..5a80c9edd8a622 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ByValueContentsMarshalling.cs @@ -0,0 +1,301 @@ +// 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.Diagnostics; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.Interop; +using Xunit; +using static Microsoft.Interop.UnitTests.TestUtils; +using StringMarshalling = System.Runtime.InteropServices.StringMarshalling; +using VerifyComInterfaceGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier; + +namespace ComInterfaceGenerator.Unit.Tests +{ + public class ByValueContentsMarshalling + { + private static IComInterfaceAttributeProvider GetAttributeProvider(GeneratorKind generator) + => generator switch + { + GeneratorKind.VTableIndexStubGenerator => new VirtualMethodIndexAttributeProvider(), + GeneratorKind.ComInterfaceGeneratorManagedObjectWrapper => new GeneratedComInterfaceAttributeProvider(System.Runtime.InteropServices.Marshalling.ComInterfaceOptions.ManagedObjectWrapper), + GeneratorKind.ComInterfaceGeneratorComObjectWrapper => new GeneratedComInterfaceAttributeProvider(System.Runtime.InteropServices.Marshalling.ComInterfaceOptions.ComObjectWrapper), + GeneratorKind.ComInterfaceGenerator => new GeneratedComInterfaceAttributeProvider(), + _ => throw new UnreachableException(), + }; + + public static IEnumerable ByValueMarshalAttributeOnValueTypes() + { + var codeSnippets = new CodeSnippets(GetAttributeProvider(GeneratorKind.ComInterfaceGenerator)); + const string In = "[{|#1:InAttribute|}]"; + const string Out = "[{|#2:OutAttribute|}]"; + const string paramName = "p"; + const string MarshalAsU4 = "[MarshalAs(UnmanagedType.U4)]"; + const string MarshalAsU2 = "[MarshalAs(UnmanagedType.U2)]"; + + string p = $$"""{|#0:{{paramName}}|}"""; + var diagnostic = new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails); + var outAttributeNotSupported = diagnostic + .WithLocation(0) + .WithArguments(SR.OutAttributeNotSupportedOnByValueParameters, paramName); + var inAttributeIsNotSupported = diagnostic + .WithLocation(0) + .WithArguments(SR.InAttributeNotSupportedOnByValueParameters, paramName); + var inOutAttributeNotSupported = diagnostic + .WithLocation(0) + .WithArguments(SR.InOutAttributeNotSupportedOnByValueParameters, paramName); + + DiagnosticResult[] InIsNotSupported = [inAttributeIsNotSupported]; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In, "int", p), InIsNotSupported }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In, "byte", p), InIsNotSupported }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + MarshalAsU4, "bool", p), InIsNotSupported }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + MarshalAsU2, "char", p), InIsNotSupported }; + + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In, "string", p, (StringMarshalling.Utf8, null)), InIsNotSupported }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In, "IntClass", p) + CodeSnippets.IntClassAndMarshaller, InIsNotSupported }; + + DiagnosticResult[] OutIsNotSupported = [outAttributeNotSupported]; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Out, "int", p), OutIsNotSupported }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Out, "IntStruct", p) + CodeSnippets.IntStructAndMarshaller, OutIsNotSupported }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Out + MarshalAsU4, "bool", p), OutIsNotSupported }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Out + MarshalAsU2, "char", p), OutIsNotSupported }; + + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Out, "string", p, (StringMarshalling.Utf8, null)), OutIsNotSupported }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Out, "IntClass", p) + CodeSnippets.IntClassAndMarshaller, OutIsNotSupported }; + + DiagnosticResult[] InOutIsNotSupported = [inOutAttributeNotSupported]; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Out, "int", p), InOutIsNotSupported }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Out, "IntStruct", p) + CodeSnippets.IntStructAndMarshaller, InOutIsNotSupported }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Out + MarshalAsU4, "bool", p), InOutIsNotSupported }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Out + MarshalAsU2, "char", p), InOutIsNotSupported }; + + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Out, "string", p, (StringMarshalling.Utf8, null)), InOutIsNotSupported }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Out, "IntClass", p) + CodeSnippets.IntClassAndMarshaller, InOutIsNotSupported }; + + // Any ref keyword is okay for non-collection types + DiagnosticResult[] None = []; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType("out", "IntStruct", p) + CodeSnippets.IntStructAndMarshaller, None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType("out", "byte", p), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(MarshalAsU4 + "out", "bool", p), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(MarshalAsU2 + "out", "char", p), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType("out", "string", p, (StringMarshalling.Utf8, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType("out", "IntClass", p) + CodeSnippets.IntClassAndMarshaller, None }; + + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType("in", "IntStruct", p) + CodeSnippets.IntStructAndMarshaller, None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType("in", "byte", p), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(MarshalAsU4 + "in", "bool", p), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(MarshalAsU2 + "in", "char", p), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType("in", "string", p, (StringMarshalling.Utf8, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType("in", "IntClass", p) + CodeSnippets.IntClassAndMarshaller, None }; + + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType("ref", "IntStruct", p) + CodeSnippets.IntStructAndMarshaller, None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType("ref", "byte", p), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(MarshalAsU4 + "ref", "bool", p), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(MarshalAsU2 + "ref", "char", p), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType("ref", "string", p, (StringMarshalling.Utf8, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType("ref", "IntClass", p) + CodeSnippets.IntClassAndMarshaller, None }; + } + + public static IEnumerable ByValueMarshalAttributeOnPinnedMarshalledTypes() + { + var codeSnippets = new CodeSnippets(GetAttributeProvider(GeneratorKind.ComInterfaceGenerator)); + const string In = "[{|#1:InAttribute|}]"; + const string Out = "[{|#2:OutAttribute|}]"; + const string paramName = "p"; + string p = $$"""{|#0:{{paramName}}|}"""; + const string Count = @"[MarshalUsing(ConstantElementCount = 10)]"; + const string MarshalAsBoolArray = "[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeConst = 10)]"; + const string MarshalUsingIntMarshaller = "[MarshalUsing(typeof(IntMarshaller), ElementIndirectionDepth = 1)]"; + const string MarshalUsingIntStructMarshaller = "[MarshalUsing(typeof(IntStructMarshaller), ElementIndirectionDepth = 1)]"; + const string MarshalUsingIntClassMarshaller = "[MarshalUsing(typeof(IntClassMarshaller), ElementIndirectionDepth = 1)]"; + + // Any explicit [In] or [Out] on an array is preferred and should not warn + DiagnosticResult[] None = []; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Count, "int[]", p), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Count, "char[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + MarshalAsBoolArray, "bool[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + MarshalUsingIntMarshaller + Count, "int[]", p) + CodeSnippets.IntMarshaller, None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Count, "string[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Count, "string[]", p, (StringMarshalling.Utf8, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Count + MarshalUsingIntStructMarshaller, "IntStruct[]", p) + CodeSnippets.IntStructAndMarshaller, None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Count + MarshalUsingIntClassMarshaller, "IntClass[]", p) + CodeSnippets.IntClassAndMarshaller, None }; + + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Out + Count, "int[]", p), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Out + Count, "char[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Out + MarshalAsBoolArray, "bool[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Out + MarshalUsingIntMarshaller + Count, "int[]", p) + CodeSnippets.IntMarshaller, None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Out + Count, "string[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Out + Count, "string[]", p, (StringMarshalling.Utf8, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Out + Count + MarshalUsingIntStructMarshaller, "IntStruct[]", p) + CodeSnippets.IntStructAndMarshaller, None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(In + Out + Count + MarshalUsingIntClassMarshaller, "IntClass[]", p) + CodeSnippets.IntClassAndMarshaller, None }; + + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Out + Count, "int[]", p), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Out + Count, "char[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Out + MarshalAsBoolArray, "bool[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Out + MarshalUsingIntMarshaller + Count, "int[]", p) + CodeSnippets.IntMarshaller, None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Out + Count, "string[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Out + Count, "string[]", p, (StringMarshalling.Utf8, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Out + Count + MarshalUsingIntStructMarshaller, "IntStruct[]", p) + CodeSnippets.IntStructAndMarshaller, None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Out + Count + MarshalUsingIntClassMarshaller, "IntClass[]", p) + CodeSnippets.IntClassAndMarshaller, None }; + + // Array parameters without [In] or [Out] should provide an Info diagnostic + var preferExplicitAttributesDiagnostic = new DiagnosticResult(GeneratorDiagnostics.GeneratedComInterfaceUsageDoesNotFollowBestPractices) + .WithLocation(0) + .WithArguments(SR.PreferExplicitInOutAttributesOnArrays); + DiagnosticResult[] PreferInOutAttributes = [preferExplicitAttributesDiagnostic]; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "int[]", p), PreferInOutAttributes }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "char[]", p, (StringMarshalling.Utf16, null)), PreferInOutAttributes }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(MarshalAsBoolArray, "bool[]", p, (StringMarshalling.Utf16, null)), PreferInOutAttributes }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(MarshalUsingIntMarshaller + Count, "int[]", p) + CodeSnippets.IntMarshaller, PreferInOutAttributes }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "string[]", p, (StringMarshalling.Utf16, null)), PreferInOutAttributes }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "string[]", p, (StringMarshalling.Utf8, null)), PreferInOutAttributes }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count + MarshalUsingIntStructMarshaller, "IntStruct[]", p) + CodeSnippets.IntStructAndMarshaller, PreferInOutAttributes }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count + MarshalUsingIntClassMarshaller, "IntClass[]", p) + CodeSnippets.IntClassAndMarshaller, PreferInOutAttributes }; + + // Ref Kinds shouldn't warn + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "in int[]", p), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "in char[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(MarshalAsBoolArray, "in bool[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(MarshalUsingIntMarshaller + Count, "in int[]", p) + CodeSnippets.IntMarshaller, None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "in string[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "in string[]", p, (StringMarshalling.Utf8, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count + MarshalUsingIntStructMarshaller, "in IntStruct[]", p) + CodeSnippets.IntStructAndMarshaller, None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count + MarshalUsingIntClassMarshaller, "in IntClass[]", p) + CodeSnippets.IntClassAndMarshaller, None }; + + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "out int[]", p), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "out char[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(MarshalAsBoolArray, "out bool[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(MarshalUsingIntMarshaller + Count, "out int[]", p) + CodeSnippets.IntMarshaller, None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "out string[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "out string[]", p, (StringMarshalling.Utf8, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count + MarshalUsingIntStructMarshaller, "out IntStruct[]", p) + CodeSnippets.IntStructAndMarshaller, None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count + MarshalUsingIntClassMarshaller, "out IntClass[]", p) + CodeSnippets.IntClassAndMarshaller, None }; + + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "ref int[]", p), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "ref char[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(MarshalAsBoolArray, "ref bool[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(MarshalUsingIntMarshaller + Count, "ref int[]", p) + CodeSnippets.IntMarshaller, None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "ref string[]", p, (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count, "ref string[]", p, (StringMarshalling.Utf8, null)), None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count + MarshalUsingIntStructMarshaller, "ref IntStruct[]", p) + CodeSnippets.IntStructAndMarshaller, None }; + yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(Count + MarshalUsingIntClassMarshaller, "ref IntClass[]", p) + CodeSnippets.IntClassAndMarshaller, None }; + } + + public static IEnumerable ByValueMarshalAttributeOnCustomCollections() + { + var codeSnippets = new CodeSnippets(GetAttributeProvider(GeneratorKind.ComInterfaceGenerator)); + const string In = "[{|#1:InAttribute|}]"; + const string Out = "[{|#2:OutAttribute|}]"; + const string paramName = "p"; + string p = $$"""{|#0:{{paramName}}|}"""; + const string CollectionMarshaller = "StatelessCollectionAllShapesMarshaller<,>"; + + var diagnostic = new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails); + var outAttributeNotSupported = diagnostic + .WithLocation(0) + .WithArguments(SR.OutAttributeNotSupportedOnByValueParameters, paramName); + var inAttributeIsNotSupported = diagnostic + .WithLocation(0) + .WithArguments(SR.InAttributeNotSupportedOnByValueParameters, paramName); + var inOutAttributeNotSupported = diagnostic + .WithLocation(0) + .WithArguments(SR.InOutAttributeNotSupportedOnByValueParameters, paramName); + + DiagnosticResult[] InIsNotSupported = [inAttributeIsNotSupported]; + DiagnosticResult[] OutIsNotSupported = [outAttributeNotSupported]; + DiagnosticResult[] InOutIsNotSupported = [inOutAttributeNotSupported]; + DiagnosticResult[] None = []; + + yield return new object[] { ID(), Source("", "int"), None }; + yield return new object[] { ID(), Source("", "byte"), None }; + yield return new object[] { ID(), Source(MarshalUsing("IntClassMarshaller", 1), "IntClass") + CodeSnippets.IntClassAndMarshaller, None }; + yield return new object[] { ID(), Source(MarshalUsing("IntStructMarshaller", 1), "IntStruct") + CodeSnippets.IntStructAndMarshaller, None }; + yield return new object[] { ID(), Source("", "string", (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), Source("", "string", (StringMarshalling.Utf8, null)), None }; + yield return new object[] { ID(), Source(MarshalCollection(1), CodeSnippets.GetCustomCollectionType("int")), None }; + + // [In] and [Out] are not allowed on custom collections + yield return new object[] { ID(), Source(In, "int"), InIsNotSupported }; + yield return new object[] { ID(), Source(In, "byte"), InIsNotSupported }; + yield return new object[] { ID(), Source(In + MarshalUsing("IntClassMarshaller", 1), "IntClass") + CodeSnippets.IntClassAndMarshaller, InIsNotSupported }; + yield return new object[] { ID(), Source(In + MarshalUsing("IntStructMarshaller", 1), "IntStruct") + CodeSnippets.IntStructAndMarshaller, InIsNotSupported }; + yield return new object[] { ID(), Source(In, "string", (StringMarshalling.Utf16, null)), InIsNotSupported }; + yield return new object[] { ID(), Source(In, "string", (StringMarshalling.Utf8, null)), InIsNotSupported }; + yield return new object[] { ID(), Source(In + MarshalCollection(1), CodeSnippets.GetCustomCollectionType("int")), InIsNotSupported }; + + yield return new object[] { ID(), Source(Out, "int"), OutIsNotSupported }; + yield return new object[] { ID(), Source(Out, "byte"), OutIsNotSupported }; + yield return new object[] { ID(), Source(Out + MarshalUsing("IntClassMarshaller", 1), "IntClass") + CodeSnippets.IntClassAndMarshaller, OutIsNotSupported }; + yield return new object[] { ID(), Source(Out + MarshalUsing("IntStructMarshaller", 1), "IntStruct") + CodeSnippets.IntStructAndMarshaller, OutIsNotSupported }; + yield return new object[] { ID(), Source(Out, "string", (StringMarshalling.Utf16, null)), OutIsNotSupported }; + yield return new object[] { ID(), Source(Out, "string", (StringMarshalling.Utf8, null)), OutIsNotSupported }; + yield return new object[] { ID(), Source(Out + MarshalCollection(1), CodeSnippets.GetCustomCollectionType("int")), OutIsNotSupported }; + + yield return new object[] { ID(), Source(In + Out, "int"), InOutIsNotSupported }; + yield return new object[] { ID(), Source(In + Out, "byte"), InOutIsNotSupported }; + yield return new object[] { ID(), Source(In + Out + MarshalUsing("IntClassMarshaller", 1), "IntClass") + CodeSnippets.IntClassAndMarshaller, InOutIsNotSupported }; + yield return new object[] { ID(), Source(In + Out + MarshalUsing("IntStructMarshaller", 1), "IntStruct") + CodeSnippets.IntStructAndMarshaller, InOutIsNotSupported }; + yield return new object[] { ID(), Source(In + Out, "string", (StringMarshalling.Utf16, null)), InOutIsNotSupported }; + yield return new object[] { ID(), Source(In + Out, "string", (StringMarshalling.Utf8, null)), InOutIsNotSupported }; + yield return new object[] { ID(), Source(In + Out + MarshalCollection(1), CodeSnippets.GetCustomCollectionType("int")), InOutIsNotSupported }; + + // RefKind modifiers are okay + yield return new object[] { ID(), SourceWithRefKind("in", "", "int"), None }; + yield return new object[] { ID(), SourceWithRefKind("in", "", "byte"), None }; + yield return new object[] { ID(), SourceWithRefKind("in", MarshalUsing("IntClassMarshaller", 1), "IntClass") + CodeSnippets.IntClassAndMarshaller, None }; + yield return new object[] { ID(), SourceWithRefKind("in", MarshalUsing("IntStructMarshaller", 1), "IntStruct") + CodeSnippets.IntStructAndMarshaller, None }; + yield return new object[] { ID(), SourceWithRefKind("in", "", "string", (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), SourceWithRefKind("in", "", "string", (StringMarshalling.Utf8, null)), None }; + yield return new object[] { ID(), SourceWithRefKind("in", MarshalCollection(1), CodeSnippets.GetCustomCollectionType("int")), None }; + + yield return new object[] { ID(), SourceWithRefKind("out", "", "int"), None }; + yield return new object[] { ID(), SourceWithRefKind("out", "", "byte"), None }; + yield return new object[] { ID(), SourceWithRefKind("out", MarshalUsing("IntClassMarshaller", 1), "IntClass") + CodeSnippets.IntClassAndMarshaller, None }; + yield return new object[] { ID(), SourceWithRefKind("out", MarshalUsing("IntStructMarshaller", 1), "IntStruct") + CodeSnippets.IntStructAndMarshaller, None }; + yield return new object[] { ID(), SourceWithRefKind("out", "", "string", (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), SourceWithRefKind("out", "", "string", (StringMarshalling.Utf8, null)), None }; + yield return new object[] { ID(), SourceWithRefKind("out", MarshalCollection(1), CodeSnippets.GetCustomCollectionType("int")), None }; + + yield return new object[] { ID(), SourceWithRefKind("ref", "", "int"), None }; + yield return new object[] { ID(), SourceWithRefKind("ref", "", "byte"), None }; + yield return new object[] { ID(), SourceWithRefKind("ref", MarshalUsing("IntClassMarshaller", 1), "IntClass") + CodeSnippets.IntClassAndMarshaller, None }; + yield return new object[] { ID(), SourceWithRefKind("ref", MarshalUsing("IntStructMarshaller", 1), "IntStruct") + CodeSnippets.IntStructAndMarshaller, None }; + yield return new object[] { ID(), SourceWithRefKind("ref", "", "string", (StringMarshalling.Utf16, null)), None }; + yield return new object[] { ID(), SourceWithRefKind("ref", "", "string", (StringMarshalling.Utf8, null)), None }; + yield return new object[] { ID(), SourceWithRefKind("ref", MarshalCollection(1), CodeSnippets.GetCustomCollectionType("int")), None }; + + string Source(string Attributes, string type, (StringMarshalling StringMarshalling, Type? StringMarshallingCustomType)? stringMarshalling = null) + => SourceWithRefKind("", Attributes, type, stringMarshalling); + + string SourceWithRefKind(string refKind, string Attributes, string type, (StringMarshalling StringMarshalling, Type? StringMarshallingCustomType)? stringMarshalling = null) + { + return codeSnippets.ByValueMarshallingOfType(Attributes + MarshalCollection(), CodeSnippets.GetCustomCollectionType(type), p, stringMarshalling) + CodeSnippets.CustomCollectionAndMarshaller; + } + static string MarshalUsing(string marshaller = CollectionMarshaller, int depth = 0) + => $"[MarshalUsing(typeof({marshaller}), ElementIndirectionDepth = {depth})]"; + static string MarshalCollection(int depth = 0) + => $"[MarshalUsing(typeof({CollectionMarshaller}), ElementIndirectionDepth = {depth}, ConstantElementCount = 10)]"; + } + + + + [Theory] + //[MemberData(nameof(ByValueMarshalAttributeOnPinnedMarshalledTypes))] + //[MemberData(nameof(ByValueMarshalAttributeOnValueTypes))] + [MemberData(nameof(ByValueMarshalAttributeOnCustomCollections))] + public async Task VerifyByValueMarshallingAttributeUsageInfoMessages(string id, string source, DiagnosticResult[] diagnostics) + { + _ = id; + VerifyComInterfaceGenerator.Test test = new(referenceAncillaryInterop: false) + { + TestCode = source, + TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck, + }; + test.DisabledDiagnostics.Remove(GeneratorDiagnostics.Ids.NotRecommendedGeneratedComInterfaceUsage); + test.ExpectedDiagnostics.AddRange(diagnostics); + await test.RunAsync(); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs index b013d8c26c4599..3a6150e4d893b3 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs @@ -49,6 +49,51 @@ private string UnmanagedCallConv(Type[]? CallConvs = null) + arguments + "]"; } + public static string GetCustomCollectionType(string elementName) => $"StatelessCollectionAllShapes<{elementName}>"; + + public const string CustomCollectionAndMarshaller = CustomCollectionDefinition + CustomCollectionAllShapesMarshaller; + public const string CustomCollectionDefinition = """ + internal class StatelessCollectionAllShapes + { + public T _field; + } + """; + public const string CustomCollectionAllShapesMarshaller = """ + [ContiguousCollectionMarshaller] + [CustomMarshaller(typeof(StatelessCollectionAllShapes<>), MarshalMode.Default, typeof(StatelessCollectionAllShapesMarshaller<,>))] + internal unsafe static class StatelessCollectionAllShapesMarshaller where TUnmanagedElement : unmanaged + { + public static void Free(TUnmanagedElement* unmanaged) { } + + // ToUnmanaged + public static TUnmanagedElement* AllocateContainerForUnmanagedElements(StatelessCollectionAllShapes managed, out int numElements) + => throw null; + public static System.ReadOnlySpan GetManagedValuesSource(StatelessCollectionAllShapes managed) // Can throw exceptions + => throw null; + public static System.Span GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements) // Can throw exceptions + => throw null; + public static ref TUnmanagedElement* GetPinnableReference(StatelessCollectionAllShapes managed) + => throw null; + + // Caller Allocated buffer ToUnmanaged + public static int BufferSize { get; } = 10; + public static TUnmanagedElement* AllocateContainerForUnmanagedElements(StatelessCollectionAllShapes managed, System.Span buffer, out int numElements) + => throw null; + + // ToManaged + public static StatelessCollectionAllShapes AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements) + => throw null; + public static System.Span GetManagedValuesDestination(StatelessCollectionAllShapes managed) + => throw null; + public static System.ReadOnlySpan GetUnmanagedValuesSource(TUnmanagedElement* unmanaged, int numElements) + => throw null; + + //ToManaged Guaranteed marshalling + public static StatelessCollectionAllShapes AllocateContainerForManagedElementsFinally(TUnmanagedElement* unmanaged, int numElements) + => throw null; + } + """; + public static readonly string DisableRuntimeMarshalling = "[assembly:System.Runtime.CompilerServices.DisableRuntimeMarshalling]"; public static readonly string UsingSystemRuntimeInteropServicesMarshalling = "using System.Runtime.InteropServices.Marshalling;"; public const string IntMarshaller = """ 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 21bd970f6cf708..60ab4ac854e65a 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 @@ -3,9 +3,7 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices.Marshalling; using System.Threading.Tasks; using Microsoft.CodeAnalysis; @@ -14,6 +12,7 @@ using Microsoft.Interop; using Microsoft.Interop.UnitTests; using Xunit; +using static Microsoft.Interop.UnitTests.TestUtils; using StringMarshalling = System.Runtime.InteropServices.StringMarshalling; using VerifyComInterfaceGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier; @@ -21,10 +20,6 @@ namespace ComInterfaceGenerator.Unit.Tests { public class CompileFails { - private static string ID( - [CallerLineNumber] int lineNumber = 0, - [CallerFilePath] string? filePath = null) - => TestUtils.GetFileLineName(lineNumber, filePath); public static IEnumerable ComInterfaceGeneratorSnippetsToCompile() { @@ -54,16 +49,6 @@ public async Task ValidateComInterfaceGeneratorSnippets(string id, string source await VerifyComInterfaceGenerator.VerifySourceGeneratorAsync(source, expectedDiagnostics); } - private static IComInterfaceAttributeProvider GetAttributeProvider(GeneratorKind generator) - => generator switch - { - GeneratorKind.VTableIndexStubGenerator => new VirtualMethodIndexAttributeProvider(), - GeneratorKind.ComInterfaceGeneratorManagedObjectWrapper => new GeneratedComInterfaceAttributeProvider(System.Runtime.InteropServices.Marshalling.ComInterfaceOptions.ManagedObjectWrapper), - GeneratorKind.ComInterfaceGeneratorComObjectWrapper => new GeneratedComInterfaceAttributeProvider(System.Runtime.InteropServices.Marshalling.ComInterfaceOptions.ComObjectWrapper), - GeneratorKind.ComInterfaceGenerator => new GeneratedComInterfaceAttributeProvider(), - _ => throw new UnreachableException(), - }; - public static IEnumerable InvalidUnmanagedToManagedCodeSnippetsToCompile(GeneratorKind generator) { CodeSnippets codeSnippets = new(GetAttributeProvider(generator)); @@ -543,340 +528,6 @@ public async Task VerifyInterfaceWithLessVisibilityThanInterfaceWarns(string id, await VerifyComInterfaceGenerator.VerifySourceGeneratorAsync(source, diagnostics); } - public static IEnumerable ByValueMarshalAttributeOnValueTypes() - { - var codeSnippets = new CodeSnippets(GetAttributeProvider(GeneratorKind.ComInterfaceGenerator)); - const string inAttribute = "[{|#1:InAttribute|}]"; - const string outAttribute = "[{|#2:OutAttribute|}]"; - const string paramName = "p"; - string paramNameWithLocation = $$"""{|#0:{{paramName}}|}"""; - var diagnostic = new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails); - var outAttributeNotSupported = diagnostic - .WithLocation(2) - .WithArguments(SR.OutAttributeNotSupportedOnByValueParameters, paramName); - var inAttributeIsNotSupported = diagnostic - .WithLocation(1) - .WithArguments(SR.InAttributeNotSupportedOnByValueParameters, paramName); - var inOutAttributeNotSupported = diagnostic - .WithLocation(1) - .WithLocation(2) - .WithArguments(SR.InOutAttributeNotSupportedOnByValueParameters, paramName); - - - // [In] is default for all non-pinned marshalled types - yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute, "int", paramNameWithLocation), new DiagnosticResult[] { - inAttributeIsNotSupported } }; - yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute, "byte", paramNameWithLocation), new DiagnosticResult[] { - inAttributeIsNotSupported } }; - yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + "[MarshalAs(UnmanagedType.U4)]", "bool", paramNameWithLocation), new DiagnosticResult[] { - inAttributeIsNotSupported } }; - yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + "[MarshalAs(UnmanagedType.U2)]", "char", paramNameWithLocation), new DiagnosticResult[] { - inAttributeIsNotSupported } }; - - yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(outAttribute, "int", paramNameWithLocation), new DiagnosticResult[] { - outAttributeNotSupported } }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(outAttribute, "IntStruct", paramNameWithLocation) + CodeSnippets.IntStructAndMarshaller, - new DiagnosticResult[] { - outAttributeNotSupported - } }; - yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(outAttribute + "[MarshalAs(UnmanagedType.U4)]", "bool", paramNameWithLocation), new DiagnosticResult[] { - outAttributeNotSupported - } }; - yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(outAttribute, "[MarshalAs(UnmanagedType.U2)] char", paramNameWithLocation), new DiagnosticResult[] { - outAttributeNotSupported - } }; - // [In,Out] should only warn for Out attribute - yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute+outAttribute, "int", paramNameWithLocation), new DiagnosticResult[] { - inOutAttributeNotSupported } }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(inAttribute+outAttribute, "IntStruct", paramNameWithLocation) + CodeSnippets.IntStructAndMarshaller, - new DiagnosticResult[] { - inOutAttributeNotSupported - } }; - yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute + "[MarshalAs(UnmanagedType.U4)]", "bool", paramNameWithLocation), new DiagnosticResult[] { - inOutAttributeNotSupported - } }; - yield return new object[] { ID(), codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute, "[MarshalAs(UnmanagedType.U2)] char", paramNameWithLocation), new DiagnosticResult[] { - inOutAttributeNotSupported - } }; - - // Any ref keyword is okay for value types - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("out", "IntStruct", paramNameWithLocation) + CodeSnippets.IntStructAndMarshaller, - new DiagnosticResult[] {} - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("out", "byte", paramNameWithLocation), - new DiagnosticResult[] {} - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("", "[MarshalAs(UnmanagedType.U2)] out char", paramNameWithLocation), - new DiagnosticResult[] {} - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("in", "IntStruct", paramNameWithLocation) + CodeSnippets.IntStructAndMarshaller, - new DiagnosticResult[] {} - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("in", "byte", paramNameWithLocation), - new DiagnosticResult[] {} - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("", "[MarshalAs(UnmanagedType.U2)] in char", paramNameWithLocation), - new DiagnosticResult[] {} - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("ref", "IntStruct", paramNameWithLocation) + CodeSnippets.IntStructAndMarshaller, - new DiagnosticResult[] {} - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("ref", "byte", paramNameWithLocation), - new DiagnosticResult[] {} - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("", "[MarshalAs(UnmanagedType.U2)] ref char", paramNameWithLocation), - new DiagnosticResult[] {} - }; - } - - public static IEnumerable ByValueMarshalAttributeOnReferenceTypes() - { - var codeSnippets = new CodeSnippets(GetAttributeProvider(GeneratorKind.ComInterfaceGenerator)); - const string inAttribute = "[{|#1:InAttribute|}]"; - const string outAttribute = "[{|#2:OutAttribute|}]"; - const string paramName = "p"; - string paramNameWithLocation = $$"""{|#0:{{paramName}}|}"""; - var inAttributeIsDefaultDiagnostic = new DiagnosticResult(GeneratorDiagnostics.UnnecessaryParameterMarshallingInfo) - .WithLocation(0) - .WithLocation(1) - .WithArguments(SR.InOutAttributes, paramName, SR.InAttributeOnlyIsDefault); - - // [In] is default - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(inAttribute, "string", paramNameWithLocation, (StringMarshalling.Utf8, null)), - new DiagnosticResult[] { inAttributeIsDefaultDiagnostic } - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(inAttribute, "IntClass", paramNameWithLocation) + CodeSnippets.IntClassAndMarshaller, - new DiagnosticResult[] { inAttributeIsDefaultDiagnostic } - }; - - var outNotAllowedOnRefTypes = new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) - .WithLocation(0) - .WithArguments(SR.OutAttributeNotSupportedOnByValueParameters, paramName); - - // [Out] is not allowed on strings - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(outAttribute, "string", paramNameWithLocation, (StringMarshalling.Utf8, null)), - new DiagnosticResult[] { outNotAllowedOnRefTypes } - }; - - // [Out] warns on by value reference types - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(outAttribute, "IntClass", paramNameWithLocation) + CodeSnippets.IntClassAndMarshaller, - new DiagnosticResult[] { outNotAllowedOnRefTypes } - }; - - // [In,Out] is fine on classes - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute, "IntClass", paramNameWithLocation) + CodeSnippets.IntClassAndMarshaller, - new DiagnosticResult[] { outNotAllowedOnRefTypes } - }; - - // All refkinds are okay on classes and strings - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("in", "string", paramNameWithLocation, (StringMarshalling.Utf8, null)), - new DiagnosticResult[] { } - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("in", "IntClass", paramNameWithLocation) + CodeSnippets.IntClassAndMarshaller, - new DiagnosticResult[] { } - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("out", "string", paramNameWithLocation, (StringMarshalling.Utf8, null)), - new DiagnosticResult[] { } - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("out", "IntClass", paramNameWithLocation) + CodeSnippets.IntClassAndMarshaller, - new DiagnosticResult[] { } - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("ref", "string", paramNameWithLocation, (StringMarshalling.Utf8, null)), - new DiagnosticResult[] { } - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("ref", "IntClass", paramNameWithLocation) + CodeSnippets.IntClassAndMarshaller, - new DiagnosticResult[] { } - }; - } - - public static IEnumerable ByValueMarshalAttributeOnPinnedMarshalledTypes() - { - var codeSnippets = new CodeSnippets(GetAttributeProvider(GeneratorKind.ComInterfaceGenerator)); - const string inAttribute = "[{|#1:InAttribute|}]"; - const string outAttribute = "[{|#2:OutAttribute|}]"; - const string paramName = "p"; - string paramNameWithLocation = $$"""{|#0:{{paramName}}|}"""; - const string constElementCount = @"[MarshalUsing(ConstantElementCount = 10)]"; - - // [In] int[] - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(inAttribute + constElementCount, "int[]", paramNameWithLocation), - new DiagnosticResult[] { } - }; - // [In] char[] blittable - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(inAttribute + constElementCount, "char[]", paramNameWithLocation, (StringMarshalling.Utf16, null)), - new DiagnosticResult[] { } - }; - - // [In] bool[] (not blittable) - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType( - inAttribute + "[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeConst = 10)]", - "bool[]", - paramNameWithLocation, - (StringMarshalling.Utf16, null)), - new DiagnosticResult[] { } - }; - // [In] int[] with custom marshaller (not blittable) - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(inAttribute, "[MarshalUsing(typeof(IntMarshaller), ElementIndirectionDepth = 1), MarshalUsing(ConstantElementCount = 10)]int[]", paramNameWithLocation) + CodeSnippets.IntMarshaller, - new DiagnosticResult[] { } - }; - // [In, Out] int[] (blittable pinned) - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute + constElementCount, "int[]", paramNameWithLocation), - new DiagnosticResult[] { } - }; - // [In, Out] char[] (utf16 blittable pinned) - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute + constElementCount, "char[]", paramNameWithLocation, (StringMarshalling.Utf16, null)), - new DiagnosticResult[] { } - }; - // [Out] int[] - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(outAttribute + constElementCount, "int[]", paramNameWithLocation), - new DiagnosticResult[] { } - }; - // [Out] char[] - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(outAttribute + constElementCount, "char[]", paramNameWithLocation, (StringMarshalling.Utf16, null)), - new DiagnosticResult[] { } - }; - - - // Without Attributes should provide info Diagnotic - var preferExplicitAttributesDiagnostic = new DiagnosticResult(GeneratorDiagnostics.GeneratedComInterfaceUsageDoesNotFollowBestPractices) - .WithLocation(0) - .WithArguments(SR.PreferExplicitInOutAttributesOnArrays); - - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(constElementCount, "int[]", paramNameWithLocation), - new DiagnosticResult[] { preferExplicitAttributesDiagnostic } - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(constElementCount, "char[]", paramNameWithLocation, (StringMarshalling.Utf16, null)), - new DiagnosticResult[] { preferExplicitAttributesDiagnostic } - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType( - inAttribute + "[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeConst = 10)]", - "bool[]", - paramNameWithLocation, - (StringMarshalling.Utf16, null)), - new DiagnosticResult[] { preferExplicitAttributesDiagnostic } - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType("", "[MarshalUsing(typeof(IntMarshaller), ElementIndirectionDepth = 1), MarshalUsing(ConstantElementCount = 10)]int[]", paramNameWithLocation) + CodeSnippets.IntMarshaller, - new DiagnosticResult[] { preferExplicitAttributesDiagnostic } - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(constElementCount, "int[]", paramNameWithLocation), - new DiagnosticResult[] { preferExplicitAttributesDiagnostic } - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(constElementCount, "char[]", paramNameWithLocation, (StringMarshalling.Utf16, null)), - new DiagnosticResult[] { preferExplicitAttributesDiagnostic } - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(constElementCount, "int[]", paramNameWithLocation), - new DiagnosticResult[] { preferExplicitAttributesDiagnostic } - }; - yield return new object[] { - ID(), - codeSnippets.ByValueMarshallingOfType(constElementCount, "char[]", paramNameWithLocation, (StringMarshalling.Utf16, null)), - new DiagnosticResult[] { preferExplicitAttributesDiagnostic } - }; - } - - [Theory] - [MemberData(nameof(ByValueMarshalAttributeOnValueTypes))] - [MemberData(nameof(ByValueMarshalAttributeOnReferenceTypes))] - public async Task VerifyByValueMarshallingAttributeUsage(string id, string source, DiagnosticResult[] diagnostics) - { - _ = id; - VerifyComInterfaceGenerator.Test test = new(referenceAncillaryInterop: false) - { - TestCode = source, - TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck, - }; - test.ExpectedDiagnostics.AddRange(diagnostics); - await test.RunAsync(); - } - - [Theory] - [MemberData(nameof(ByValueMarshalAttributeOnPinnedMarshalledTypes))] - public async Task VerifyByValueMarshallingAttributeUsageInfoMessages(string id, string source, DiagnosticResult[] diagnostics) - { - _ = id; - VerifyComInterfaceGenerator.Test test = new(referenceAncillaryInterop: false) - { - TestCode = source, - TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck, - }; - test.ExpectedDiagnostics.AddRange(diagnostics); - await test.RunAsync(); - } - [Fact] public async Task VerifyNonPartialInterfaceWarns() { diff --git a/src/libraries/System.Runtime.InteropServices/tests/Common/TestUtils.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/TestUtils.cs index 4d1ec3a5d2c7dd..9972434579abb4 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/Common/TestUtils.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/Common/TestUtils.cs @@ -1,13 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Testing; using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; @@ -15,6 +12,11 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; +using ComInterfaceGenerator.Unit.Tests; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; using Xunit; namespace Microsoft.Interop.UnitTests @@ -51,6 +53,10 @@ public enum TestTargetFramework public static class TestUtils { + public static string ID( + [CallerLineNumber] int lineNumber = 0, + [CallerFilePath] string? filePath = null) + => TestUtils.GetFileLineName(lineNumber, filePath); internal static string GetFileLineName( [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) @@ -61,6 +67,16 @@ internal static void Use(T _) // Workaround for - xUnit1026 // Theory methods should use all of their parameters } + internal static IComInterfaceAttributeProvider GetAttributeProvider(GeneratorKind generator) + => generator switch + { + GeneratorKind.VTableIndexStubGenerator => new VirtualMethodIndexAttributeProvider(), + GeneratorKind.ComInterfaceGeneratorManagedObjectWrapper => new GeneratedComInterfaceAttributeProvider(System.Runtime.InteropServices.Marshalling.ComInterfaceOptions.ManagedObjectWrapper), + GeneratorKind.ComInterfaceGeneratorComObjectWrapper => new GeneratedComInterfaceAttributeProvider(System.Runtime.InteropServices.Marshalling.ComInterfaceOptions.ComObjectWrapper), + GeneratorKind.ComInterfaceGenerator => new GeneratedComInterfaceAttributeProvider(), + _ => throw new UnreachableException(), + }; + /// /// Disable binding redirect warnings. They are disabled by default by the .NET SDK, but not by Roslyn. /// See https://github.com/dotnet/roslyn/issues/19640. @@ -298,7 +314,7 @@ public void Stop() int count = Interlocked.Decrement(ref _count); if (count == 0) { - Environment.SetEnvironmentVariable(EnvVarName, null); + Environment.SetEnvironmentVariable(EnvVarName, null); } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IIntArray.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IIntArray.cs index fbc68dcf4dbca0..55e657c1ae2da7 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IIntArray.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IIntArray.cs @@ -5,8 +5,51 @@ using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; -namespace SharedTypes.ComInterfaces +namespace SharedTypes.ComInterfaces.asdf { + [global::System.Runtime.InteropServices.Marshalling.GeneratedComInterface(), global::System.Runtime.InteropServices.Guid("0A52B77C-E08B-4274-A1F4-1A2BF2C07E60")] + partial interface INaiveAPI + { + + void Method([MarshalUsing(ConstantElementCount = 10)] StatelessCollectionAllShapes p); + } + internal class StatelessCollectionAllShapes + { + public T _field; + } + [ContiguousCollectionMarshaller] + [CustomMarshaller(typeof(StatelessCollectionAllShapes<>), MarshalMode.Default, typeof(StatelessCollectionAllShapesMarshaller<,>))] + internal unsafe static class StatelessCollectionAllShapesMarshaller where TUnmanagedElement : unmanaged + { + public static void Free(TUnmanagedElement* unmanaged) { } + + // ToUnmanaged + public static TUnmanagedElement* AllocateContainerForUnmanagedElements(StatelessCollectionAllShapes managed, out int numElements) + => throw null; + public static System.ReadOnlySpan GetManagedValuesSource(StatelessCollectionAllShapes managed) // Can throw exceptions + => throw null; + public static System.Span GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements) // Can throw exceptions + => throw null; + public static ref TUnmanagedElement* GetPinnableReference(StatelessCollectionAllShapes managed) + => throw null; + + // Caller Allocated buffer ToUnmanaged + public static int BufferSize { get; } = 10; + public static TUnmanagedElement* AllocateContainerForUnmanagedElements(StatelessCollectionAllShapes managed, System.Span buffer, out int numElements) + => throw null; + + // ToManaged + public static StatelessCollectionAllShapes AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements) + => throw null; + public static System.Span GetManagedValuesDestination(StatelessCollectionAllShapes managed) + => throw null; + public static System.ReadOnlySpan GetUnmanagedValuesSource(TUnmanagedElement* unmanaged, int numElements) + => throw null; + + //ToManaged Guaranteed marshalling + public static StatelessCollectionAllShapes AllocateContainerForManagedElementsFinally(TUnmanagedElement* unmanaged, int numElements) + => throw null; + } [GeneratedComInterface] [Guid("9FA4A8A9-3D8F-48A8-B6FB-B45B5F1B9FB6")] internal partial interface IIntArray diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionAllShapes.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionAllShapes.cs index b9aeecd69d10a3..d8ceefdc72130b 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionAllShapes.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionAllShapes.cs @@ -11,7 +11,7 @@ namespace SharedTypes.ComInterfaces [Guid("4731FA5D-C103-4A22-87A1-58DCEDD4A9B3")] internal partial interface IStatelessCollectionAllShapes { - void Method([MarshalUsing(CountElementName = nameof(size))] StatelessCollectionAllShapes param, int size); + void Method([MarshalUsing(typeof(StatelessCollectionAllShapesMarshaller<,>), ConstantElementCount = 10)] StatelessCollectionAllShapes param, int size); void MethodIn([MarshalUsing(CountElementName = nameof(size))] in StatelessCollectionAllShapes param, int size); void MethodOut([MarshalUsing(CountElementName = nameof(size))] out StatelessCollectionAllShapes param, out int size); void MethodRef([MarshalUsing(CountElementName = nameof(size))] ref StatelessCollectionAllShapes param, int size); @@ -22,7 +22,7 @@ internal partial interface IStatelessCollectionAllShapes StatelessCollectionAllShapes ReturnPreserveSig(out int size); } - [NativeMarshalling(typeof(StatelessCollectionAllShapesMarshaller<,>))] + //[NativeMarshalling(typeof(StatelessCollectionAllShapesMarshaller<,>))] internal class StatelessCollectionAllShapes { } From b03475cd5ab50440cc47de7db4651868e8945c40 Mon Sep 17 00:00:00 2001 From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com> Date: Thu, 24 Aug 2023 13:16:11 -0700 Subject: [PATCH 4/5] Added LibraryImport tests --- docs/project/list-of-diagnostics.md | 2 +- .../GeneratorDiagnostics.cs | 3 +- .../ByValueContentsMarshalling.cs | 4 +- .../CodeSnippets.cs | 15 ++ .../CompileFails.cs | 11 +- .../tests/Common/TestUtils.cs | 12 -- .../ByValueContentsMarshalling.cs | 135 ++++++++++++++++++ .../CodeSnippets.cs | 16 +++ .../CompileFails.cs | 57 -------- .../Compiles.cs | 24 ---- .../SharedTypes/ComInterfaces/IIntArray.cs | 45 +----- .../IStatelessCollectionAllShapes.cs | 4 +- 12 files changed, 179 insertions(+), 149 deletions(-) create mode 100644 src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/ByValueContentsMarshalling.cs diff --git a/docs/project/list-of-diagnostics.md b/docs/project/list-of-diagnostics.md index 3c9a9afb9c4199..4b46d49f5813f0 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`__ | 'GenerateComInterfaceAttribute' usage not recommended. See aka.ms/GeneratedComInterfaceUsage for recommended usage. | +| __`SYSLIB1092`__ | Usage of '[LibraryImport|GeneratedComInterface]' does not follow recommendation. See aka.ms/[LibraryImport|GeneratedComInterface]Usage for best practices. | | __`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/GeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs index fd2132e826c15e..e4bcba1350fed0 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs @@ -493,7 +493,8 @@ public class Ids GetResourceString(nameof(SR.ComInterfaceUsageDoesNotFollowBestPracticesMessageWithDetails)), Category, DiagnosticSeverity.Info, - isEnabledByDefault: true); + isEnabledByDefault: true, + helpLinkUri: "aka.ms/GeneratedComInterfaceUsage"); /// /// Report diagnostic for invalid configuration for string marshalling. diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ByValueContentsMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ByValueContentsMarshalling.cs index 5a80c9edd8a622..fdd2d33d6e7d27 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ByValueContentsMarshalling.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ByValueContentsMarshalling.cs @@ -282,8 +282,8 @@ static string MarshalCollection(int depth = 0) [Theory] - //[MemberData(nameof(ByValueMarshalAttributeOnPinnedMarshalledTypes))] - //[MemberData(nameof(ByValueMarshalAttributeOnValueTypes))] + [MemberData(nameof(ByValueMarshalAttributeOnPinnedMarshalledTypes))] + [MemberData(nameof(ByValueMarshalAttributeOnValueTypes))] [MemberData(nameof(ByValueMarshalAttributeOnCustomCollections))] public async Task VerifyByValueMarshallingAttributeUsageInfoMessages(string id, string source, DiagnosticResult[] diagnostics) { diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs index 3a6150e4d893b3..700797fcb3e888 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -12,12 +13,26 @@ namespace ComInterfaceGenerator.Unit.Tests { internal partial class CodeSnippets { + internal static IComInterfaceAttributeProvider GetAttributeProvider(GeneratorKind generator) + => generator switch + { + GeneratorKind.VTableIndexStubGenerator => new VirtualMethodIndexAttributeProvider(), + GeneratorKind.ComInterfaceGeneratorManagedObjectWrapper => new GeneratedComInterfaceAttributeProvider(System.Runtime.InteropServices.Marshalling.ComInterfaceOptions.ManagedObjectWrapper), + GeneratorKind.ComInterfaceGeneratorComObjectWrapper => new GeneratedComInterfaceAttributeProvider(System.Runtime.InteropServices.Marshalling.ComInterfaceOptions.ComObjectWrapper), + GeneratorKind.ComInterfaceGenerator => new GeneratedComInterfaceAttributeProvider(), + _ => throw new UnreachableException(), + }; + private readonly IComInterfaceAttributeProvider _attributeProvider; public CodeSnippets(IComInterfaceAttributeProvider attributeProvider) { _attributeProvider = attributeProvider; } + public CodeSnippets(GeneratorKind generator) : this(GetAttributeProvider(generator)) + { + } + private string VirtualMethodIndex( int index, bool? ImplicitThisParameter = null, 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 60ab4ac854e65a..331fa54117fb04 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 @@ -20,7 +20,6 @@ namespace ComInterfaceGenerator.Unit.Tests { public class CompileFails { - public static IEnumerable ComInterfaceGeneratorSnippetsToCompile() { CodeSnippets codeSnippets = new(new GeneratedComInterfaceAttributeProvider()); @@ -51,7 +50,7 @@ public async Task ValidateComInterfaceGeneratorSnippets(string id, string source public static IEnumerable InvalidUnmanagedToManagedCodeSnippetsToCompile(GeneratorKind generator) { - CodeSnippets codeSnippets = new(GetAttributeProvider(generator)); + CodeSnippets codeSnippets = new(generator); string safeHandleMarshallerDoesNotSupportManagedToUnmanaged = string.Format(SR.ManagedToUnmanagedMissingRequiredMarshaller, "global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller"); string safeHandleMarshallerDoesNotSupportUnmanagedToManaged = string.Format(SR.UnmanagedToManagedMissingRequiredMarshaller, "global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller"); @@ -83,7 +82,7 @@ public static IEnumerable InvalidUnmanagedToManagedCodeSnippetsToCompi DiagnosticResult invalidReturnTypeDiagnostic = VerifyComInterfaceGenerator.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails) .WithLocation(0) .WithArguments(marshallerDoesNotSupportManagedToUnmanaged, "Method"); - CustomStructMarshallingCodeSnippets customStructMarshallingCodeSnippets = new(new CodeSnippets.Bidirectional(GetAttributeProvider(generator))); + CustomStructMarshallingCodeSnippets customStructMarshallingCodeSnippets = new(new CodeSnippets.Bidirectional(CodeSnippets.GetAttributeProvider(generator))); yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateless.NativeToManagedOnlyOutParameter, new[] { invalidManagedToUnmanagedParameterDiagnostic } }; yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateless.NativeToManagedOnlyReturnValue, new[] { invalidReturnTypeDiagnostic } }; yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateless.ByValueInParameter, new[] { invalidUnmanagedToManagedParameterDiagnostic } }; @@ -98,7 +97,7 @@ public static IEnumerable StringMarshallingCodeSnippets(GeneratorKind string CustomTypeSpecifiedWithNoStringMarshallingCustom = SR.InvalidStringMarshallingConfigurationNotCustom; string StringMarshallingMustMatchBase = SR.GeneratedComInterfaceStringMarshallingMustMatchBase; - CodeSnippets codeSnippets = new(GetAttributeProvider(generator)); + CodeSnippets codeSnippets = new(generator); (StringMarshalling, Type?) utf8Marshalling = (StringMarshalling.Utf8, null); (StringMarshalling, Type?) utf16Marshalling = (StringMarshalling.Utf16, null); (StringMarshalling, Type?) customUtf16Marshalling = (StringMarshalling.Custom, typeof(Utf16StringMarshaller)); @@ -327,7 +326,7 @@ public static IEnumerable InvalidManagedToUnmanagedCodeSnippetsToCompi { // Marshallers with only support for their expected places in the signatures in // UnmanagedToManaged marshal modes. - CustomStructMarshallingCodeSnippets customStructMarshallingCodeSnippets = new(new CodeSnippets.Bidirectional(GetAttributeProvider(generator))); + CustomStructMarshallingCodeSnippets customStructMarshallingCodeSnippets = new(new CodeSnippets.Bidirectional(CodeSnippets.GetAttributeProvider(generator))); yield return new[] { ID(), customStructMarshallingCodeSnippets.Stateless.NativeToManagedOnlyInParameter }; yield return new[] { ID(), customStructMarshallingCodeSnippets.Stateless.ByValueOutParameter }; @@ -686,7 +685,7 @@ partial interface {|#0:J|} public static IEnumerable CountParameterIsOutSnippets() { - var g = GetAttributeProvider(GeneratorKind.ComInterfaceGenerator); + var g = CodeSnippets.GetAttributeProvider(GeneratorKind.ComInterfaceGenerator); CodeSnippets a = new(g); DiagnosticResult returnValueDiag = new DiagnosticResult(GeneratorDiagnostics.SizeOfInCollectionMustBeDefinedAtCallReturnValue) .WithLocation(1) diff --git a/src/libraries/System.Runtime.InteropServices/tests/Common/TestUtils.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/TestUtils.cs index 9972434579abb4..cd065f54a48c0b 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/Common/TestUtils.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/Common/TestUtils.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; -using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; @@ -12,7 +11,6 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; -using ComInterfaceGenerator.Unit.Tests; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Diagnostics; @@ -67,16 +65,6 @@ internal static void Use(T _) // Workaround for - xUnit1026 // Theory methods should use all of their parameters } - internal static IComInterfaceAttributeProvider GetAttributeProvider(GeneratorKind generator) - => generator switch - { - GeneratorKind.VTableIndexStubGenerator => new VirtualMethodIndexAttributeProvider(), - GeneratorKind.ComInterfaceGeneratorManagedObjectWrapper => new GeneratedComInterfaceAttributeProvider(System.Runtime.InteropServices.Marshalling.ComInterfaceOptions.ManagedObjectWrapper), - GeneratorKind.ComInterfaceGeneratorComObjectWrapper => new GeneratedComInterfaceAttributeProvider(System.Runtime.InteropServices.Marshalling.ComInterfaceOptions.ComObjectWrapper), - GeneratorKind.ComInterfaceGenerator => new GeneratedComInterfaceAttributeProvider(), - _ => throw new UnreachableException(), - }; - /// /// Disable binding redirect warnings. They are disabled by default by the .NET SDK, but not by Roslyn. /// See https://github.com/dotnet/roslyn/issues/19640. diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/ByValueContentsMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/ByValueContentsMarshalling.cs new file mode 100644 index 00000000000000..e632481d52109f --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/ByValueContentsMarshalling.cs @@ -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; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.Interop; +using Xunit; +using static Microsoft.Interop.UnitTests.TestUtils; +using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier; + +namespace LibraryImportGenerator.UnitTests +{ + public class ByValueContentsMarshalling + { + public static IEnumerable ByValueMarshalAttributeOnValueTypes() + { + CodeSnippets.ByValueParameterWithModifier("int[]", "In"); + + const string In = "InAttribute"; + const string Out = "OutAttribute"; + const string InOut = "InAttribute, OutAttribute"; + const string paramName = "p"; + const string MarshalUsingUtf16 = "MarshalUsing(typeof(Utf16StringMarshaller))"; + + var diagnostic = new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails); + var outAttributeNotSupported = diagnostic + .WithLocation(0) + .WithArguments(SR.OutAttributeNotSupportedOnByValueParameters, paramName); + var inAttributeIsNotSupported = diagnostic + .WithLocation(0) + .WithArguments(SR.InAttributeNotSupportedOnByValueParameters, paramName); + var inOutAttributeNotSupported = diagnostic + .WithLocation(0) + .WithArguments(SR.InOutAttributeNotSupportedOnByValueParameters, paramName); + + DiagnosticResult[] InIsNotSupported = [inAttributeIsNotSupported]; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("int", In), InIsNotSupported }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("byte", In), InIsNotSupported }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("string", In + " , " + MarshalUsingUtf16), InIsNotSupported }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("IntStruct", In, CodeSnippets.IntStructAndMarshaller), InIsNotSupported }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("IntClass", In, CodeSnippets.IntClassAndMarshaller), InIsNotSupported }; + + DiagnosticResult[] OutIsNotSupported = [outAttributeNotSupported]; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("int", Out), OutIsNotSupported }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("byte", Out), OutIsNotSupported }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("string", Out + " , " + MarshalUsingUtf16), OutIsNotSupported }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("IntStruct", Out, CodeSnippets.IntStructAndMarshaller), OutIsNotSupported }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("IntClass", Out, CodeSnippets.IntClassAndMarshaller), OutIsNotSupported }; + + DiagnosticResult[] InOutIsNotSupported = [inOutAttributeNotSupported]; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("int", InOut), InOutIsNotSupported }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("byte", InOut), InOutIsNotSupported }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("string", InOut + " , " + MarshalUsingUtf16), InOutIsNotSupported }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("IntStruct", InOut, CodeSnippets.IntStructAndMarshaller), InOutIsNotSupported }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("IntClass", InOut, CodeSnippets.IntClassAndMarshaller), InOutIsNotSupported }; + + var inAndOutNotAllowedWithRefKind = new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) + .WithLocation(0) + .WithArguments("The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead.", "p"); + DiagnosticResult[] InAndOutNotAllowedWithRefKind = [inAndOutNotAllowedWithRefKind]; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("in int", In), InAndOutNotAllowedWithRefKind }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("ref int", In), InAndOutNotAllowedWithRefKind }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("ref int", InOut), InAndOutNotAllowedWithRefKind }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("out int", Out), InAndOutNotAllowedWithRefKind }; + } + + public static IEnumerable ByValueMarshalAttributeOnArrays() + { + CodeSnippets.ByValueParameterWithModifier("int[]", "In"); + + const string In = "InAttribute"; + const string Out = "OutAttribute"; + const string InOut = "InAttribute, OutAttribute"; + const string MarshalUsingUtf16 = "MarshalUsing(typeof(Utf16StringMarshaller), ElementIndirectionDepth = 1)"; + const string Count = "MarshalUsing(ConstantElementCount = 10)"; + DiagnosticResult[] None = []; + + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("int[]", string.Join(',', Count, In)), None }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("byte[]", string.Join(',', Count, In)), None }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("string[]", string.Join(',', Count, In, MarshalUsingUtf16)), None }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("IntStruct[]", string.Join(',', Count, In), CodeSnippets.IntStructAndMarshaller), None }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("IntClass[]", string.Join(',', Count, In), CodeSnippets.IntClassAndMarshaller), None }; + + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("int[]", string.Join(',', Count, Out)), None }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("byte[]", string.Join(',', Count, Out)), None }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("string[]", string.Join(',', Count, Out, MarshalUsingUtf16)), None }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("IntStruct[]", string.Join(',', Count, Out), CodeSnippets.IntStructAndMarshaller), None }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("IntClass[]", string.Join(',', Count, Out), CodeSnippets.IntClassAndMarshaller), None }; + + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("int[]", string.Join(',', Count, InOut)), None }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("byte[]", string.Join(',', Count, InOut)), None }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("string[]", string.Join(',', Count, InOut, MarshalUsingUtf16)), None }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("IntStruct[]", string.Join(',', Count, InOut), CodeSnippets.IntStructAndMarshaller), None }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("IntClass[]", string.Join(',', Count, InOut), CodeSnippets.IntClassAndMarshaller), None }; + + DiagnosticResult preferAttributes = new DiagnosticResult(GeneratorDiagnostics.LibraryImportUsageDoesNotFollowBestPractices) + .WithArguments(SR.PreferExplicitInOutAttributesOnArrays) + .WithLocation(0); + DiagnosticResult[] PreferAttributes = [preferAttributes]; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("int[]", Count), PreferAttributes }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("byte[]", Count), PreferAttributes }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("string[]", string.Join(',', Count, MarshalUsingUtf16)), PreferAttributes }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("IntStruct[]", Count, CodeSnippets.IntStructAndMarshaller), PreferAttributes }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("IntClass[]", Count, CodeSnippets.IntClassAndMarshaller), PreferAttributes }; + + var inAndOutNotAllowedWithRefKind = new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) + .WithLocation(0) + .WithArguments("The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead.", "p"); + DiagnosticResult[] InAndOutNotAllowedWithRefKind = [inAndOutNotAllowedWithRefKind]; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("in int[]", string.Join(',', Count, In)), InAndOutNotAllowedWithRefKind }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("ref int[]", string.Join(',', Count, In)), InAndOutNotAllowedWithRefKind }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("ref int[]", string.Join(',', Count, In, Out)), InAndOutNotAllowedWithRefKind }; + yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("out int[]", string.Join(',', Count, Out)), InAndOutNotAllowedWithRefKind }; + } + + + [Theory] + [MemberData(nameof(ByValueMarshalAttributeOnValueTypes))] + [MemberData(nameof(ByValueMarshalAttributeOnArrays))] + public async Task VerifyByValueMarshallingAttributeUsageInfoMessages(string id, string source, DiagnosticResult[] diagnostics) + { + _ = id; + VerifyCS.Test test = new(referenceAncillaryInterop: false) + { + TestCode = source, + TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck, + }; + test.DisabledDiagnostics.Remove(GeneratorDiagnostics.Ids.NotRecommendedGeneratedComInterfaceUsage); + test.ExpectedDiagnostics.AddRange(diagnostics); + await test.RunAsync(); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs index e1039f70a90ef9..19832861a38aaa 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs @@ -986,6 +986,22 @@ out int pOutSize } """; + public const string IntClassAndMarshaller = IntClassDefinition + IntClassMarshallerDefinition; + public const string IntClassDefinition = """ + internal struct IntClass + { + public int Field; + } + """; + public const string IntClassMarshallerDefinition = """ + [CustomMarshaller(typeof(IntClass), MarshalMode.Default, typeof(IntClassMarshaller))] + internal static class IntClassMarshaller + { + public static nint ConvertToUnmanaged(IntClass managed) => (nint)0; + public static IntClass ConvertToManaged(nint unmanaged) => default; + } + """; + public const string IntStructAndMarshaller = IntStructDefinition + IntStructMarshallerDefinition; public const string IntStructDefinition = """ internal struct IntStruct diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs index ffb3fb5c6a14ba..2d278dc6237de2 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs @@ -350,56 +350,6 @@ public static IEnumerable CodeSnippetsToCompile() .WithArguments("MarshalAsAttribute", "t") }}; - // Unsupported [In, Out] attributes usage - - // By ref with [In, Out] attributes - yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("in int", "In"), new[] - { - VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) - .WithLocation(0) - .WithArguments("The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead.", "p") - } }; - yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("ref int", "In"), new[] - { - VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) - .WithLocation(0) - .WithArguments("The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead.", "p") - } }; - yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("ref int", "In, Out"), new[] - { - VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) - .WithLocation(0) - .WithArguments("The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead.", "p") - } }; - yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("out int", "Out"), new[] - { - VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) - .WithLocation(0) - .WithArguments("The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead.", "p") - } }; - - // By value non-array with [In, Out] attributes - yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("{|#1:In|}"), new [] { - VerifyCS.Diagnostic(GeneratorDiagnostics.UnnecessaryParameterMarshallingInfo) - .WithLocation(0) - .WithLocation(1) - .WithArguments(SR.InOutAttributes, "p", SR.InAttributeOnlyIsDefault) - .WithSeverity(DiagnosticSeverity.Info) - } }; - yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("Out"), new[] - { - VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) - .WithLocation(0) - .WithArguments(SR.OutAttributeNotSupportedOnByValueParameters, "p") - } }; - - yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("In, Out"), new[] - { - VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails) - .WithLocation(0) - .WithArguments(SR.OutAttributeNotSupportedOnByValueParameters, "p") - } }; - // LCIDConversion yield return new object[] { ID(), CodeSnippets.LCIDConversionAttribute, new[] { VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationNotSupported) @@ -832,13 +782,6 @@ public static IEnumerable CodeSnippetsToCompile() .WithLocation(1) .WithArguments("ref return", "Basic.RefReadonlyReturn()"), } }; - yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("{|#10:In|}"), new[] - { - VerifyCS.Diagnostic(GeneratorDiagnostics.UnnecessaryParameterMarshallingInfo) - .WithLocation(0) - .WithLocation(10) - .WithArguments("[In] and [Out] attributes", "p", SR.InAttributeOnlyIsDefault) - } }; } [Theory] diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs index 438d589b2c29d0..5d37fffd52a5b6 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs @@ -17,7 +17,6 @@ using Microsoft.CodeAnalysis.Text; using Microsoft.Interop.UnitTests; using Xunit; -using GeneratorDiagnostics = Microsoft.Interop.GeneratorDiagnostics; using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier; namespace LibraryImportGenerator.UnitTests @@ -744,28 +743,5 @@ public NoChangeTest(TestTargetFramework framework) return (newCompilation, diagnostics); } } - - public static IEnumerable ByValueMarshalKindSnippets() - { - // Blittable array - yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("{|#10:Out|}"), new DiagnosticResult[] { } }; - - yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("{|#10:In|}, {|#11:Out|}"), new DiagnosticResult[] { } }; - - yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("{|#10:In|}"), new DiagnosticResult[] { - VerifyCS.Diagnostic(GeneratorDiagnostics.UnnecessaryParameterMarshallingInfo) - .WithLocation(0) - .WithLocation(10) - .WithArguments("[In] and [Out] attributes", "p", SR.InAttributeOnlyIsDefault) - } }; - } - - [MemberData(nameof(ByValueMarshalKindSnippets))] - [Theory] - public async Task ValidateDiagnosticsForUnnecessaryByValueMarshalKindAttributes(string id, string source, DiagnosticResult[] diagnostics) - { - _ = id; - await VerifyCS.VerifySourceGeneratorAsync(source, diagnostics); - } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IIntArray.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IIntArray.cs index 55e657c1ae2da7..fbc68dcf4dbca0 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IIntArray.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IIntArray.cs @@ -5,51 +5,8 @@ using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; -namespace SharedTypes.ComInterfaces.asdf +namespace SharedTypes.ComInterfaces { - [global::System.Runtime.InteropServices.Marshalling.GeneratedComInterface(), global::System.Runtime.InteropServices.Guid("0A52B77C-E08B-4274-A1F4-1A2BF2C07E60")] - partial interface INaiveAPI - { - - void Method([MarshalUsing(ConstantElementCount = 10)] StatelessCollectionAllShapes p); - } - internal class StatelessCollectionAllShapes - { - public T _field; - } - [ContiguousCollectionMarshaller] - [CustomMarshaller(typeof(StatelessCollectionAllShapes<>), MarshalMode.Default, typeof(StatelessCollectionAllShapesMarshaller<,>))] - internal unsafe static class StatelessCollectionAllShapesMarshaller where TUnmanagedElement : unmanaged - { - public static void Free(TUnmanagedElement* unmanaged) { } - - // ToUnmanaged - public static TUnmanagedElement* AllocateContainerForUnmanagedElements(StatelessCollectionAllShapes managed, out int numElements) - => throw null; - public static System.ReadOnlySpan GetManagedValuesSource(StatelessCollectionAllShapes managed) // Can throw exceptions - => throw null; - public static System.Span GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements) // Can throw exceptions - => throw null; - public static ref TUnmanagedElement* GetPinnableReference(StatelessCollectionAllShapes managed) - => throw null; - - // Caller Allocated buffer ToUnmanaged - public static int BufferSize { get; } = 10; - public static TUnmanagedElement* AllocateContainerForUnmanagedElements(StatelessCollectionAllShapes managed, System.Span buffer, out int numElements) - => throw null; - - // ToManaged - public static StatelessCollectionAllShapes AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements) - => throw null; - public static System.Span GetManagedValuesDestination(StatelessCollectionAllShapes managed) - => throw null; - public static System.ReadOnlySpan GetUnmanagedValuesSource(TUnmanagedElement* unmanaged, int numElements) - => throw null; - - //ToManaged Guaranteed marshalling - public static StatelessCollectionAllShapes AllocateContainerForManagedElementsFinally(TUnmanagedElement* unmanaged, int numElements) - => throw null; - } [GeneratedComInterface] [Guid("9FA4A8A9-3D8F-48A8-B6FB-B45B5F1B9FB6")] internal partial interface IIntArray diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionAllShapes.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionAllShapes.cs index d8ceefdc72130b..ec103fa3a37bd7 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionAllShapes.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionAllShapes.cs @@ -11,7 +11,7 @@ namespace SharedTypes.ComInterfaces [Guid("4731FA5D-C103-4A22-87A1-58DCEDD4A9B3")] internal partial interface IStatelessCollectionAllShapes { - void Method([MarshalUsing(typeof(StatelessCollectionAllShapesMarshaller<,>), ConstantElementCount = 10)] StatelessCollectionAllShapes param, int size); + void Method([MarshalUsing(ConstantElementCount = 10)] StatelessCollectionAllShapes param, int size); void MethodIn([MarshalUsing(CountElementName = nameof(size))] in StatelessCollectionAllShapes param, int size); void MethodOut([MarshalUsing(CountElementName = nameof(size))] out StatelessCollectionAllShapes param, out int size); void MethodRef([MarshalUsing(CountElementName = nameof(size))] ref StatelessCollectionAllShapes param, int size); @@ -22,7 +22,7 @@ internal partial interface IStatelessCollectionAllShapes StatelessCollectionAllShapes ReturnPreserveSig(out int size); } - //[NativeMarshalling(typeof(StatelessCollectionAllShapesMarshaller<,>))] + [NativeMarshalling(typeof(StatelessCollectionAllShapesMarshaller<,>))] internal class StatelessCollectionAllShapes { } From 89f14b9801cfaef4c74419efa188953db91009b7 Mon Sep 17 00:00:00 2001 From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com> Date: Thu, 24 Aug 2023 13:24:58 -0700 Subject: [PATCH 5/5] Cleaned up some code --- .../ByValueMarshalKindSupportDescriptor.cs | 10 ++-- .../BestPracticeMessagesTests.cs | 48 ------------------- .../IStatelessCollectionAllShapes.cs | 2 +- .../TestAssets/SharedTypes/SharedTypes.csproj | 1 + 4 files changed, 7 insertions(+), 54 deletions(-) delete mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs index 0469da175069c1..7754e177d66063 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs @@ -7,7 +7,7 @@ namespace Microsoft.Interop { - public record struct ByValueMarshalKindSupportVariant(ByValueMarshalKindSupport Support, string? details) + public record struct ByValueMarshalKindSupportInfo(ByValueMarshalKindSupport Support, string? details) { public ByValueMarshalKindSupport GetSupport(TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) { @@ -43,10 +43,10 @@ public ByValueMarshalKindSupport GetSupport(TypePositionInfo info, StubCodeConte /// Provides an implementation of through /// public record ByValueMarshalKindSupportDescriptor( - ByValueMarshalKindSupportVariant DefaultSupport, - ByValueMarshalKindSupportVariant InSupport, - ByValueMarshalKindSupportVariant OutSupport, - ByValueMarshalKindSupportVariant InOutSupport) + ByValueMarshalKindSupportInfo DefaultSupport, + ByValueMarshalKindSupportInfo InSupport, + ByValueMarshalKindSupportInfo OutSupport, + ByValueMarshalKindSupportInfo InOutSupport) { /// /// A default for by value parameters. [In] is allowed, but unnecessary. Out is not allowed. diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs deleted file mode 100644 index a8a26b4547732a..00000000000000 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/BestPracticeMessagesTests.cs +++ /dev/null @@ -1,48 +0,0 @@ - -// 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.Threading.Tasks; -using Microsoft.CodeAnalysis.Testing; -using Microsoft.Interop; -using Xunit; -using VerifyComInterfaceGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier; - - -namespace ComInterfaceGenerator.Unit.Tests -{ - public class BestPracticesMessagesTests - { - [Fact] - public async Task ArrayParameterWithNoAttributesGivesMessage() - { - var source = $$""" - using System.Runtime.InteropServices; - using System.Runtime.InteropServices.Marshalling; - - [GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)] - [Guid("a4a20815-f1f2-4fa6-ada7-ecb05ac60d30")] - internal partial interface IFoo - { - void BlittableArray([MarshalUsing(CountElementName = nameof(size))] int[] {|#0:param|}, int size); - void BlittableOutArray([MarshalUsing(CountElementName = nameof(size))] out int[] param, int size); - void MaybeBlittableArray([MarshalUsing(CountElementName = nameof(size))] char[] {|#1:param|}, int size); - void NonBlittableArray([MarshalUsing(CountElementName = nameof(size))] IntStruct[] {|#2:param|}, int size); - } - """ + CodeSnippets.IntStructAndMarshaller; - var diagnostic = new DiagnosticResult(GeneratorDiagnostics.GeneratedComInterfaceUsageDoesNotFollowBestPractices) - .WithArguments(SR.PreferExplicitInOutAttributesOnArrays); - - VerifyComInterfaceGenerator.Test test = new(referenceAncillaryInterop: false) - { - TestCode = source, - TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck, - CompilerDiagnostics = CompilerDiagnostics.All, - }; - test.DisabledDiagnostics.Remove(GeneratorDiagnostics.Ids.NotRecommendedGeneratedComInterfaceUsage); - test.ExpectedDiagnostics.AddRange([diagnostic.WithLocation(0), diagnostic.WithLocation(1), diagnostic.WithLocation(2)]); - await test.RunAsync(); - } - } -} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionAllShapes.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionAllShapes.cs index ec103fa3a37bd7..b9aeecd69d10a3 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionAllShapes.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionAllShapes.cs @@ -11,7 +11,7 @@ namespace SharedTypes.ComInterfaces [Guid("4731FA5D-C103-4A22-87A1-58DCEDD4A9B3")] internal partial interface IStatelessCollectionAllShapes { - void Method([MarshalUsing(ConstantElementCount = 10)] StatelessCollectionAllShapes param, int size); + void Method([MarshalUsing(CountElementName = nameof(size))] StatelessCollectionAllShapes param, int size); void MethodIn([MarshalUsing(CountElementName = nameof(size))] in StatelessCollectionAllShapes param, int size); void MethodOut([MarshalUsing(CountElementName = nameof(size))] out StatelessCollectionAllShapes param, out int size); void MethodRef([MarshalUsing(CountElementName = nameof(size))] ref StatelessCollectionAllShapes param, int size); diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj index f55883a3de833e..790a5e3f05a366 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj @@ -11,6 +11,7 @@ +