From 5cd3dfecd35660679e92553f933b6e48191ce460 Mon Sep 17 00:00:00 2001 From: Christoph Bergmeister Date: Thu, 1 Mar 2018 00:07:56 +0000 Subject: [PATCH 1/3] Fix parsing the -Settings object as a path when the path is an expression that is not fully evaluated yet. --- Engine/Settings.cs | 4 ++++ Tests/Engine/InvokeScriptAnalyzer.tests.ps1 | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/Engine/Settings.cs b/Engine/Settings.cs index 0947b77d8..72706b5ff 100644 --- a/Engine/Settings.cs +++ b/Engine/Settings.cs @@ -703,6 +703,10 @@ internal static SettingsMode FindSettingsMode(object settings, string path, out { settingsMode = SettingsMode.Hashtable; } + else // if the provided object is wrapped in multiple expressions then it might not be resolved yet at this stage -> try using the File type as a last resort and best guess. + { + settingsMode = SettingsMode.File; + } } } diff --git a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 index e358d42c5..4f582e16b 100644 --- a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 +++ b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 @@ -397,6 +397,18 @@ Describe "Test CustomizedRulePath" { } } + It "Should process relative settings path even when settings path object is an expression" { + try { + $initialLocation = Get-Location + Set-Location $PSScriptRoot + $warnings = Invoke-ScriptAnalyzer -ScriptDefinition 'gci' -Settings (Join-Path (Get-Location).Path '.\SettingsTest\..\SettingsTest\Project1\PSScriptAnalyzerSettings.psd1') + $warnings.Count | Should -Be 1 + } + finally { + Set-Location $initialLocation + } + } + It "Should use the CustomRulePath parameter" { $settings = @{ CustomRulePath = "$directory\CommunityAnalyzerRules" From da48f8a7f49172733f5d950789c34d8cc9a2a3aa Mon Sep 17 00:00:00 2001 From: Christoph Bergmeister Date: Sat, 3 Mar 2018 11:03:16 +0000 Subject: [PATCH 2/3] address PR comments, improve verbose logging and tidy up --- Engine/Settings.cs | 39 ++++++++++++--------- Engine/Strings.Designer.cs | 11 +++++- Engine/Strings.resx | 5 ++- Tests/Engine/InvokeScriptAnalyzer.tests.ps1 | 12 +++---- 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/Engine/Settings.cs b/Engine/Settings.cs index 72706b5ff..a52463abf 100644 --- a/Engine/Settings.cs +++ b/Engine/Settings.cs @@ -202,13 +202,25 @@ internal static Settings Create(object settingsObj, string cwd, IOutputWriter ou case SettingsMode.Preset: case SettingsMode.File: - var resolvedPath = getResolvedProviderPathFromPSPathDelegate(settingsFound.ToString(), out ProviderInfo providerInfo).Single(); - settingsFound = resolvedPath; - outputWriter?.WriteVerbose( - String.Format( - CultureInfo.CurrentCulture, - Strings.SettingsUsingFile, - resolvedPath)); + var userProvidedSettingsString = settingsFound.ToString(); + try + { + var resolvedPath = getResolvedProviderPathFromPSPathDelegate(userProvidedSettingsString, out ProviderInfo providerInfo).Single(); + settingsFound = resolvedPath; + outputWriter?.WriteVerbose( + String.Format( + CultureInfo.CurrentCulture, + Strings.SettingsUsingFile, + resolvedPath)); + } + catch + { + outputWriter?.WriteVerbose( + String.Format( + CultureInfo.CurrentCulture, + Strings.SettingsCannotFindFile, + userProvidedSettingsString)); + } break; case SettingsMode.Hashtable: @@ -218,20 +230,15 @@ internal static Settings Create(object settingsObj, string cwd, IOutputWriter ou Strings.SettingsUsingHashtable)); break; - default: // case SettingsMode.None + default: outputWriter?.WriteVerbose( String.Format( CultureInfo.CurrentCulture, - Strings.SettingsCannotFindFile)); - break; - } - - if (settingsMode != SettingsMode.None) - { - return new Settings(settingsFound); + Strings.SettingsObjectCouldNotBResolved)); + return null; } - return null; + return new Settings(settingsFound); } /// diff --git a/Engine/Strings.Designer.cs b/Engine/Strings.Designer.cs index 1f8db8c92..d7234f283 100644 --- a/Engine/Strings.Designer.cs +++ b/Engine/Strings.Designer.cs @@ -458,7 +458,7 @@ internal static string SettingsAutoDiscovered { } /// - /// Looks up a localized string similar to Cannot find a settings file.. + /// Looks up a localized string similar to Cannot resolve settings file path '{0}'.. /// internal static string SettingsCannotFindFile { get { @@ -511,6 +511,15 @@ internal static string SettingsNotProvided { } } + /// + /// Looks up a localized string similar to Settings object could not be resolved.. + /// + internal static string SettingsObjectCouldNotBResolved { + get { + return ResourceManager.GetString("SettingsObjectCouldNotBResolved", resourceCulture); + } + } + /// /// Looks up a localized string similar to Using settings file at {0}.. /// diff --git a/Engine/Strings.resx b/Engine/Strings.resx index 5194830c3..99d90761f 100644 --- a/Engine/Strings.resx +++ b/Engine/Strings.resx @@ -268,7 +268,7 @@ Using settings hashtable. - Cannot find a settings file. + Cannot resolve settings file path '{0}'. Cannot parse settings. Will abort the invocation. @@ -321,4 +321,7 @@ Input position should be less than that of the invoking object. + + Settings object could not be resolved. + \ No newline at end of file diff --git a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 index 4f582e16b..554749bb2 100644 --- a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 +++ b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 @@ -387,25 +387,23 @@ Describe "Test CustomizedRulePath" { Context "When used from settings file" { It "Should process relative settings path" { try { - $initialLocation = Get-Location - Set-Location $PSScriptRoot + Push-Location $PSScriptRoot $warnings = Invoke-ScriptAnalyzer -ScriptDefinition 'gci' -Settings .\SettingsTest\..\SettingsTest\Project1\PSScriptAnalyzerSettings.psd1 $warnings.Count | Should -Be 1 } finally { - Set-Location $initialLocation + Pop-Location } } - It "Should process relative settings path even when settings path object is an expression" { + It "Should process relative settings path even when settings path object is not resolved to a string yet" { try { - $initialLocation = Get-Location - Set-Location $PSScriptRoot + Push-Location $PSScriptRoot $warnings = Invoke-ScriptAnalyzer -ScriptDefinition 'gci' -Settings (Join-Path (Get-Location).Path '.\SettingsTest\..\SettingsTest\Project1\PSScriptAnalyzerSettings.psd1') $warnings.Count | Should -Be 1 } finally { - Set-Location $initialLocation + Pop-Location } } From f2eada8e75960f70ac9a6f98e383b0d0f920b497 Mon Sep 17 00:00:00 2001 From: Christoph Bergmeister Date: Sun, 4 Mar 2018 15:32:12 +0000 Subject: [PATCH 3/3] Improve check for file type by trying to cast to PSObject and checking its BaseObject property. --- Engine/Settings.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Engine/Settings.cs b/Engine/Settings.cs index a52463abf..35a941781 100644 --- a/Engine/Settings.cs +++ b/Engine/Settings.cs @@ -710,9 +710,15 @@ internal static SettingsMode FindSettingsMode(object settings, string path, out { settingsMode = SettingsMode.Hashtable; } - else // if the provided object is wrapped in multiple expressions then it might not be resolved yet at this stage -> try using the File type as a last resort and best guess. + else // if the provided argument is wrapped in an expressions then PowerShell resolves it but it will be of type PSObject and we have to operate then on the BaseObject { - settingsMode = SettingsMode.File; + if (settingsFound is PSObject settingsFoundPSObject) + { + if (settingsFoundPSObject.BaseObject is String) + { + settingsMode = SettingsMode.File; + } + } } } }