mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
179 lines
5.2 KiB
PowerShell
179 lines
5.2 KiB
PowerShell
|
|
#
|
|
# Run the new parser, return either errors or the ast
|
|
#
|
|
function Get-ParseResults
|
|
{
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(ValueFromPipeline=$True,Mandatory=$True)]
|
|
[string]$src,
|
|
[switch]$Ast
|
|
)
|
|
|
|
$errors = $null
|
|
$result = [System.Management.Automation.Language.Parser]::ParseInput($src, [ref]$null, [ref]$errors)
|
|
if ($Ast) { $result } else { ,$errors }
|
|
}
|
|
|
|
#
|
|
# Run script and return errors
|
|
#
|
|
function Get-RuntimeError
|
|
{
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(ValueFromPipeline=$True,Mandatory=$True)]
|
|
[string]$src
|
|
)
|
|
|
|
$errors = $null
|
|
try
|
|
{
|
|
[scriptblock]::Create($src).Invoke() > $null
|
|
}
|
|
catch
|
|
{
|
|
return $_.Exception.InnerException.ErrorRecord
|
|
}
|
|
}
|
|
|
|
function position_message
|
|
{
|
|
param($position)
|
|
|
|
if ($position.Line.Length -lt $position.ColumnNumber)
|
|
{
|
|
$position.Line + " <<<<"
|
|
}
|
|
else
|
|
{
|
|
$position.Line.Insert($position.ColumnNumber, " <<<<")
|
|
}
|
|
}
|
|
|
|
|
|
#
|
|
# Run the new parser, check the errors against the expected errors
|
|
#
|
|
function Test-Error
|
|
{
|
|
[CmdletBinding()]
|
|
param([string]$src, [string[]]$expectedErrors, [int[]]$expectedOffsets)
|
|
|
|
Assert ($expectedErrors.Count -eq $expectedOffsets.Count) "Test case error"
|
|
|
|
$errors = Get-ParseResults -Src $src
|
|
|
|
|
|
if ($null -ne $errors)
|
|
{
|
|
Assert ($errors.Count -eq $expectedErrors.Count) "Expected $($expectedErrors.Count) errors, got $($errors.Count)"
|
|
for ($i = 0; $i -lt $errors.Count; ++$i)
|
|
{
|
|
$err = $errors[$i]
|
|
Assert ($expectedErrors[$i] -eq $err.ErrorId) ("Unexpected error: {0,-30}{1}" -f ("$($err.ErrorId):",
|
|
(position_message $err.Extent.StartScriptPosition)))
|
|
Assert ($expectedOffsets[$i] -eq $err.Extent.StartScriptPosition.Offset) `
|
|
"Expected position: $($expectedOffsets[$i]), got $($err.Extent.StartScriptPosition.Offset)"
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Assert $false "Expected errors but didn't receive any."
|
|
}
|
|
}
|
|
|
|
#
|
|
# Pester friendly version of Test-Error
|
|
#
|
|
function ShouldBeParseError
|
|
{
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$src,
|
|
[string[]]$expectedErrors,
|
|
[int[]]$expectedOffsets,
|
|
# This is a temporary solution after moving type creation from parse time to runtime
|
|
[switch]$SkipAndCheckRuntimeError
|
|
)
|
|
|
|
Context "Parse error expected: <<$src>>" {
|
|
# Test case error if this fails
|
|
$expectedErrors.Count | Should Be $expectedOffsets.Count
|
|
|
|
if ($SkipAndCheckRuntimeError)
|
|
{
|
|
It "error should happen at parse time, not at runtime" -Skip {}
|
|
$errors = Get-RuntimeError -Src $src
|
|
# for runtime errors we will only get the first one
|
|
$expectedErrors = ,$expectedErrors[0]
|
|
$expectedOffsets = ,$expectedOffsets[0]
|
|
}
|
|
else
|
|
{
|
|
$errors = Get-ParseResults -Src $src
|
|
}
|
|
|
|
It "Error count" { $errors.Count | Should Be $expectedErrors.Count }
|
|
for ($i = 0; $i -lt $errors.Count; ++$i)
|
|
{
|
|
$err = $errors[$i]
|
|
|
|
if ($SkipAndCheckRuntimeError)
|
|
{
|
|
$errorId = $err.FullyQualifiedErrorId
|
|
}
|
|
else
|
|
{
|
|
$errorId = $err.ErrorId
|
|
}
|
|
It "Error Id" { $errorId | Should Be $expectedErrors[$i] }
|
|
It "Error position" -Pending:$SkipAndCheckRuntimeError { $err.Extent.StartScriptPosition.Offset | Should Be $expectedOffsets[$i] }
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function Flatten-Ast
|
|
{
|
|
[CmdletBinding()]
|
|
param([System.Management.Automation.Language.Ast] $ast)
|
|
|
|
$ast
|
|
$ast | gm -type property | ? { ($prop = $_.Name) -ne 'Parent' } | % {
|
|
$ast.$prop | ? { $_ -is [System.Management.Automation.Language.Ast] } | % { Flatten-Ast $_ }
|
|
}
|
|
}
|
|
|
|
function Test-ErrorStmt
|
|
{
|
|
param([string]$src, [string]$errorStmtExtent)
|
|
|
|
$ast = Get-ParseResults $src -Ast
|
|
$asts = @(Flatten-Ast $ast.EndBlock.Statements[0])
|
|
|
|
Assert ($asts[0] -is [System.Management.Automation.Language.ErrorStatementAst]) "Expected error statement"
|
|
Assert ($asts.Count -eq $args.Count + 1) "Incorrect number of nested asts"
|
|
Assert ($asts[0].Extent.Text -eq $errorStmtExtent) "Error statement expected <$errorStmtExtent>, got <$($asts[0].Extent.Text)>"
|
|
for ($i = 0; $i -lt $args.Count; ++$i)
|
|
{
|
|
Assert ($asts[$i + 1].Extent.Text -eq $args[$i]) "Nested ast incorrect: <$($asts[$i+1].Extent.Text)>, expected <$($args[$i])>"
|
|
}
|
|
}
|
|
|
|
function Test-Ast
|
|
{
|
|
param([string]$src)
|
|
|
|
$ast = Get-ParseResults $src -Ast
|
|
$asts = @(Flatten-Ast $ast)
|
|
Assert ($asts.Count -eq $args.Count) "Incorrect number of nested asts, got $($asts.Count), expected $($args.Count)"
|
|
for ($i = 0; $i -lt $args.Count; ++$i)
|
|
{
|
|
Assert ($asts[$i].Extent.Text -eq $args[$i]) "Nested ast incorrect: <$($asts[$i].Extent.Text)>, expected <$($args[$i])>"
|
|
}
|
|
}
|
|
|
|
Export-ModuleMember -Function Test-Error, Test-ErrorStmt, Test-Ast, ShouldBeParseError, Get-ParseResults, Get-RuntimeError
|