From 8787c65b6574106b831101b41107b9c0e99df2bf Mon Sep 17 00:00:00 2001 From: Jordan Borean Date: Tue, 6 Nov 2018 10:48:31 +1000 Subject: [PATCH] powershell: add ability to ignore specific warnings in C# Add-Type (#47643) --- .../Ansible.ModuleUtils.AddType.psm1 | 33 +++++++++++++++++-- .../library/add_type_test.ps1 | 21 ++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 b/lib/ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 index 09591583c35..a6a521bfcab 100644 --- a/lib/ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +++ b/lib/ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 @@ -70,6 +70,7 @@ Function Add-CSharpType { # pattern used to find referenced assemblies in the code $assembly_pattern = "^//\s*AssemblyReference\s+-Name\s+(?[\w.]*)(\s+-CLR\s+(?Core|Framework))?$" + $no_warn_pattern = "^//\s*NoWarn\s+-Name\s+(?[\w\d]*)(\s+-CLR\s+(?Core|Framework))?$" # PSCore vs PSDesktop use different methods to compile the code, # PSCore uses Roslyn and can compile the code purely in memory @@ -85,12 +86,14 @@ Function Add-CSharpType { [Microsoft.CodeAnalysis.CompilationReference]::CreateFromFile(([System.Reflection.Assembly]::GetAssembly([PSObject])).Location) ) $netcore_app_ref_folder = [System.IO.Path]::Combine([System.IO.Path]::GetDirectoryName([PSObject].Assembly.Location), "ref") + $lib_assembly_location = [System.IO.Path]::GetDirectoryName([object].Assembly.Location) foreach ($file in [System.IO.Directory]::EnumerateFiles($netcore_app_ref_folder, "*.dll", [System.IO.SearchOption]::TopDirectoryOnly)) { $assemblies.Add([Microsoft.CodeAnalysis.MetadataReference]::CreateFromFile($file)) > $null } # loop through the references, parse as a SyntaxTree and get # referenced assemblies + $ignore_warnings = New-Object -TypeName 'System.Collections.Generic.Dictionary`2[[String], [Microsoft.CodeAnalysis.ReportDiagnostic]]' $parse_options = ([Microsoft.CodeAnalysis.CSharp.CSharpParseOptions]::Default).WithPreprocessorSymbols($defined_symbols) $syntax_trees = [System.Collections.Generic.List`1[Microsoft.CodeAnalysis.SyntaxTree]]@() foreach ($reference in $References) { @@ -104,7 +107,17 @@ Function Add-CSharpType { if ($Matches.ContainsKey("CLR") -and $Matches.CLR -ne "Core") { continue } - $assemblies.Add($Matches.Name) > $null + $assembly_path = $Matches.Name + if (-not ([System.IO.Path]::IsPathRooted($assembly_path))) { + $assembly_path = Join-Path -Path $lib_assembly_location -ChildPath $assembly_path + } + $assemblies.Add([Microsoft.CodeAnalysis.MetadataReference]::CreateFromFile($assembly_path)) > $null + } + if ($line -imatch $no_warn_pattern) { + if ($Matches.ContainsKey("CLR") -and $Matches.CLR -ne "Core") { + continue + } + $ignore_warnings.Add($Matches.Name, [Microsoft.CodeAnalysis.ReportDiagnostic]::Suppress) } } } finally { @@ -122,6 +135,7 @@ Function Add-CSharpType { # set warnings to error out if IgnoreWarnings is not set if (-not $IgnoreWarnings.IsPresent) { $compiler_options = $compiler_options.WithGeneralDiagnosticOption([Microsoft.CodeAnalysis.ReportDiagnostic]::Error) + $compiler_options = $compiler_options.WithSpecificDiagnosticOptions($ignore_warnings) } # create compilation object @@ -201,7 +215,6 @@ Function Add-CSharpType { } $compile_parameters = New-Object -TypeName System.CodeDom.Compiler.CompilerParameters - $compile_parameters.CompilerOptions = [String]::Join(" ", $compiler_options.ToArray()) $compile_parameters.GenerateExecutable = $false $compile_parameters.GenerateInMemory = $true $compile_parameters.TreatWarningsAsErrors = (-not $IgnoreWarnings.IsPresent) @@ -219,6 +232,7 @@ Function Add-CSharpType { # create a code snippet for each reference and check if we need # to reference any extra assemblies # //AssemblyReference -Name ... [-CLR Framework] + $ignore_warnings = [System.Collections.ArrayList]@() $compile_units = [System.Collections.Generic.List`1[System.CodeDom.CodeSnippetCompileUnit]]@() foreach ($reference in $References) { $sr = New-Object -TypeName System.IO.StringReader -ArgumentList $reference @@ -231,13 +245,28 @@ Function Add-CSharpType { } $assemblies.Add($Matches.Name) > $null } + if ($line -imatch $no_warn_pattern) { + if ($Matches.ContainsKey("CLR") -and $Matches.CLR -ne "Framework") { + continue + } + $warning_id = $Matches.Name + # /nowarn should only contain the numeric part + if ($warning_id.StartsWith("CS")) { + $warning_id = $warning_id.Substring(2) + } + $ignore_warnings.Add($warning_id) > $null + } } } finally { $sr.Close() } $compile_units.Add((New-Object -TypeName System.CodeDom.CodeSnippetCompileUnit -ArgumentList $reference)) > $null } + if ($ignore_warnings.Count -gt 0) { + $compiler_options.Add("/nowarn:" + ([String]::Join(",", $ignore_warnings.ToArray()))) > $null + } $compile_parameters.ReferencedAssemblies.AddRange($assemblies) + $compile_parameters.CompilerOptions = [String]::Join(" ", $compiler_options.ToArray()) # compile the code together and check for errors $provider = New-Object -TypeName Microsoft.CSharp.CSharpCodeProvider diff --git a/test/integration/targets/win_module_utils/library/add_type_test.ps1 b/test/integration/targets/win_module_utils/library/add_type_test.ps1 index f27a1d9c58e..4516c35e675 100644 --- a/test/integration/targets/win_module_utils/library/add_type_test.ps1 +++ b/test/integration/targets/win_module_utils/library/add_type_test.ps1 @@ -183,5 +183,26 @@ Add-CSharpType -References $reference_1, $reference_2 $actual = [Namespace6.Class6]::GetString() Assert-Equals -actual $actual -expected "Hello World" +$ignored_warning = @' +using System; + +//NoWarn -Name CS0219 + +namespace Namespace7 +{ + public class Class7 + { + public static string GetString() + { + string a = ""; + return "abc"; + } + } +} +'@ +Add-CSharpType -References $ignored_warning +$actual = [Namespace7.Class7]::GetString() +Assert-Equals -actual $actual -expected "abc" + $result.res = "success" Exit-Json -obj $result