From 94e10e02ac43d93ac32916db0a4b285f74518f41 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 27 Feb 2023 13:29:02 -0800 Subject: [PATCH 1/8] Fix `ConciseView` to handle custom `ParserError` ErrorRecords --- .../PowerShellCore_format_ps1xml.cs | 4 +++- .../engine/Formatting/ErrorView.Tests.ps1 | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs index 3d6257f36a8..25491452e84 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs @@ -1075,6 +1075,8 @@ private static IEnumerable ViewsOf_System_Management_Autom ") .AddScriptBlockExpressionBinding(@" Set-StrictMode -Off + $ErrorActionPreference = 'Stop' + trap { 'Error found in error view definition: ' + $_.Exception.Message } $newline = [Environment]::Newline $resetColor = '' @@ -1106,7 +1108,7 @@ function Get-ConciseViewPositionMessage { $prefix = '' # Don't show line information if script module - if (($myinv -and $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1 -or $err.CategoryInfo.Category -eq 'ParserError') -and !($myinv.ScriptName.EndsWith('.psm1', [System.StringComparison]::OrdinalIgnoreCase))) { + if (($myinv -and $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1 -or $err.Type -is [System.Management.Automation.ParseException]) -and !($myinv.ScriptName -and $myinv.ScriptName.EndsWith('.psm1', [System.StringComparison]::OrdinalIgnoreCase))) { $useTargetObject = $false # Handle case where there is a TargetObject and we can show the error at the target rather than the script source diff --git a/test/powershell/engine/Formatting/ErrorView.Tests.ps1 b/test/powershell/engine/Formatting/ErrorView.Tests.ps1 index 18173354a65..af5e5603cca 100644 --- a/test/powershell/engine/Formatting/ErrorView.Tests.ps1 +++ b/test/powershell/engine/Formatting/ErrorView.Tests.ps1 @@ -151,6 +151,21 @@ Describe 'Tests for $ErrorView' -Tag CI { $e | Should -Not -BeNullOrEmpty $e | Should -Not -BeLike "*Line*" } + + It 'Parser error shows line information' { + $testScript = '$psstyle.outputrendering = "plaintext"; 1 ++ 1' + $e = & "$PSHOME/pwsh" -noprofile -command $testScript 2>&1 | Out-String + $e | Should -Not -BeNullOrEmpty + $e = $e.Split([Environment]::NewLine) + $e[0] | Should -BeLike "ParserError:*" + $e[1] | Should -BeLike "Line *" + $e[2] | Should -BeLike "*|*1 ++ 1*" + } + + It 'Faux remote parser error shows concise message' { + start-job { [cmdletbinding()]param() $e = [System.Management.Automation.ErrorRecord]::new([System.Exception]::new('hello'), 1, 'ParserError', $null); $pscmdlet.ThrowTerminatingError($e) } | Wait-Job | Receive-Job -ErrorVariable e -ErrorAction SilentlyContinue + $e | Out-String | Should -BeLike '*ParserError*' + } } Context 'NormalView tests' { From 6e4efb3eaeaeeeec0dbeb9c6632d19600d6d3fc9 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 27 Feb 2023 15:59:09 -0800 Subject: [PATCH 2/8] Fix how to check that the error is a parse error --- .../DefaultFormatters/PowerShellCore_format_ps1xml.cs | 7 +++---- test/powershell/engine/Formatting/ErrorView.Tests.ps1 | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs index 25491452e84..5b521085b06 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs @@ -1089,7 +1089,7 @@ private static IEnumerable ViewsOf_System_Management_Autom $accentColor = $PSStyle.Formatting.ErrorAccent } - function Get-ConciseViewPositionMessage { + function Get-ConciseViewPositionMessage( $err ) { # returns a string cut to last whitespace function Get-TruncatedString($string, [int]$length) { @@ -1108,9 +1108,8 @@ function Get-ConciseViewPositionMessage { $prefix = '' # Don't show line information if script module - if (($myinv -and $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1 -or $err.Type -is [System.Management.Automation.ParseException]) -and !($myinv.ScriptName -and $myinv.ScriptName.EndsWith('.psm1', [System.StringComparison]::OrdinalIgnoreCase))) { + if (((($err.CategoryInfo.Category -eq 'ParserError' -and $err.Exception -is 'System.Management.Automation.ParentContainsErrorRecordException') -or $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1)) -and !($myinv.ScriptName -match '\.psm1$')) { $useTargetObject = $false - # Handle case where there is a TargetObject and we can show the error at the target rather than the script source if ($_.TargetObject.Line -and $_.TargetObject.LineText) { $posmsg = ""${resetcolor}$($_.TargetObject.File)${newline}"" @@ -1298,7 +1297,7 @@ function Get-ConciseViewPositionMessage { $posmsg = '' if ($ErrorView -eq 'ConciseView') { - $posmsg = Get-ConciseViewPositionMessage + $posmsg = Get-ConciseViewPositionMessage -Err $_ } elseif ($myinv -and ($myinv.MyCommand -or ($err.CategoryInfo.Category -ne 'ParserError'))) { $posmsg = $myinv.PositionMessage diff --git a/test/powershell/engine/Formatting/ErrorView.Tests.ps1 b/test/powershell/engine/Formatting/ErrorView.Tests.ps1 index af5e5603cca..2188648872a 100644 --- a/test/powershell/engine/Formatting/ErrorView.Tests.ps1 +++ b/test/powershell/engine/Formatting/ErrorView.Tests.ps1 @@ -109,7 +109,7 @@ Describe 'Tests for $ErrorView' -Tag CI { } It "Error shows if `$PSModuleAutoLoadingPreference is set to 'none'" { - $e = & "$PSHOME/pwsh" -noprofile -command '$PSModuleAutoLoadingPreference = ""none""; cmdletThatDoesntExist' 2>&1 | Out-String + $e = & "$PSHOME/pwsh" -noprofile -command '$PSModuleAutoLoadingPreference = "none"; cmdletThatDoesntExist' 2>&1 | Out-String $e | Should -BeLike "*cmdletThatDoesntExist*" } @@ -158,7 +158,7 @@ Describe 'Tests for $ErrorView' -Tag CI { $e | Should -Not -BeNullOrEmpty $e = $e.Split([Environment]::NewLine) $e[0] | Should -BeLike "ParserError:*" - $e[1] | Should -BeLike "Line *" + $e[1] | Should -BeLike "Line *" -Because ($e | Out-String) $e[2] | Should -BeLike "*|*1 ++ 1*" } From ca502963e8de87f6bbc04dfb7ac6d0b0b663e71b Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 27 Feb 2023 16:33:58 -0800 Subject: [PATCH 3/8] Revert unneeded change to pass in original error to get concise message --- .../DefaultFormatters/PowerShellCore_format_ps1xml.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs index 5b521085b06..dbb4d99b0a4 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs @@ -1089,7 +1089,7 @@ private static IEnumerable ViewsOf_System_Management_Autom $accentColor = $PSStyle.Formatting.ErrorAccent } - function Get-ConciseViewPositionMessage( $err ) { + function Get-ConciseViewPositionMessage() { # returns a string cut to last whitespace function Get-TruncatedString($string, [int]$length) { @@ -1297,7 +1297,7 @@ private static IEnumerable ViewsOf_System_Management_Autom $posmsg = '' if ($ErrorView -eq 'ConciseView') { - $posmsg = Get-ConciseViewPositionMessage -Err $_ + $posmsg = Get-ConciseViewPositionMessage } elseif ($myinv -and ($myinv.MyCommand -or ($err.CategoryInfo.Category -ne 'ParserError'))) { $posmsg = $myinv.PositionMessage From 411da6ba0943d28b155ad6342c26e6bce0962adf Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 27 Feb 2023 16:38:11 -0800 Subject: [PATCH 4/8] add some comments explaining checks --- .../DefaultFormatters/PowerShellCore_format_ps1xml.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs index dbb4d99b0a4..0c3be3c3bb0 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs @@ -1107,7 +1107,10 @@ private static IEnumerable ViewsOf_System_Management_Autom $message = '' $prefix = '' - # Don't show line information if script module + # The checks here determine if we show line detailed error information: + # - check if `ParserError` and comes from PowerShell which eventually results in a ParseException, but during this execution it's an ErrorRecord + # - check if invocation is a script or multiple lines in the console + # - check that it's not a script module as expectation is that users don't want to see the line of error within a module if (((($err.CategoryInfo.Category -eq 'ParserError' -and $err.Exception -is 'System.Management.Automation.ParentContainsErrorRecordException') -or $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1)) -and !($myinv.ScriptName -match '\.psm1$')) { $useTargetObject = $false # Handle case where there is a TargetObject and we can show the error at the target rather than the script source From f554b741caa6cff172559e48de4cd477482d2210 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 27 Feb 2023 17:20:06 -0800 Subject: [PATCH 5/8] Update src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs Co-authored-by: Dongbo Wang --- .../DefaultFormatters/PowerShellCore_format_ps1xml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs index 0c3be3c3bb0..05692b98858 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs @@ -1089,7 +1089,7 @@ private static IEnumerable ViewsOf_System_Management_Autom $accentColor = $PSStyle.Formatting.ErrorAccent } - function Get-ConciseViewPositionMessage() { + function Get-ConciseViewPositionMessage { # returns a string cut to last whitespace function Get-TruncatedString($string, [int]$length) { From 1e6339eaf27b46681a675c67a6c18f9cdee8e53a Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 27 Feb 2023 17:20:28 -0800 Subject: [PATCH 6/8] Update src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs Co-authored-by: Dongbo Wang --- .../DefaultFormatters/PowerShellCore_format_ps1xml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs index 05692b98858..8f170ab4aa8 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs @@ -1111,7 +1111,7 @@ function Get-ConciseViewPositionMessage { # - check if `ParserError` and comes from PowerShell which eventually results in a ParseException, but during this execution it's an ErrorRecord # - check if invocation is a script or multiple lines in the console # - check that it's not a script module as expectation is that users don't want to see the line of error within a module - if (((($err.CategoryInfo.Category -eq 'ParserError' -and $err.Exception -is 'System.Management.Automation.ParentContainsErrorRecordException') -or $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1)) -and !($myinv.ScriptName -match '\.psm1$')) { + if ((($err.CategoryInfo.Category -eq 'ParserError' -and $err.Exception -is 'System.Management.Automation.ParentContainsErrorRecordException') -or $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1) -and !($myinv.ScriptName -match '\.psm1$')) { $useTargetObject = $false # Handle case where there is a TargetObject and we can show the error at the target rather than the script source if ($_.TargetObject.Line -and $_.TargetObject.LineText) { From 5bef8deea0c9d317be77a1f3bc81365ae150ac29 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 27 Feb 2023 17:31:14 -0800 Subject: [PATCH 7/8] add space separating code and comment --- .../DefaultFormatters/PowerShellCore_format_ps1xml.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs index 8f170ab4aa8..3195d913fc8 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs @@ -1113,6 +1113,7 @@ function Get-ConciseViewPositionMessage { # - check that it's not a script module as expectation is that users don't want to see the line of error within a module if ((($err.CategoryInfo.Category -eq 'ParserError' -and $err.Exception -is 'System.Management.Automation.ParentContainsErrorRecordException') -or $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1) -and !($myinv.ScriptName -match '\.psm1$')) { $useTargetObject = $false + # Handle case where there is a TargetObject and we can show the error at the target rather than the script source if ($_.TargetObject.Line -and $_.TargetObject.LineText) { $posmsg = ""${resetcolor}$($_.TargetObject.File)${newline}"" From 0008479df0bc83fcfa87236532dc09dab410cc6a Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Tue, 28 Feb 2023 16:25:03 -0800 Subject: [PATCH 8/8] Update src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs Co-authored-by: Dongbo Wang --- .../DefaultFormatters/PowerShellCore_format_ps1xml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs index 3195d913fc8..747c083ee51 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs @@ -1111,7 +1111,7 @@ function Get-ConciseViewPositionMessage { # - check if `ParserError` and comes from PowerShell which eventually results in a ParseException, but during this execution it's an ErrorRecord # - check if invocation is a script or multiple lines in the console # - check that it's not a script module as expectation is that users don't want to see the line of error within a module - if ((($err.CategoryInfo.Category -eq 'ParserError' -and $err.Exception -is 'System.Management.Automation.ParentContainsErrorRecordException') -or $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1) -and !($myinv.ScriptName -match '\.psm1$')) { + if ((($err.CategoryInfo.Category -eq 'ParserError' -and $err.Exception -is 'System.Management.Automation.ParentContainsErrorRecordException') -or $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1) -and $myinv.ScriptName -notmatch '\.psm1$') { $useTargetObject = $false # Handle case where there is a TargetObject and we can show the error at the target rather than the script source