Throw better parsing error when statements should be put in named block (#6434)

This commit is contained in:
Dongbo Wang 2018-03-21 14:24:20 -07:00 committed by GitHub
parent 41b3161830
commit 9df8ea58e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 4 deletions

View file

@ -1620,7 +1620,8 @@ namespace System.Management.Automation.Language
? lCurly.Extent
: (paramBlockAst != null) ? paramBlockAst.Extent : null;
IScriptExtent endExtent = null;
IScriptExtent extent;
IScriptExtent extent = null;
IScriptExtent scriptBlockExtent = null;
while (true)
{
@ -1628,7 +1629,28 @@ namespace System.Management.Automation.Language
switch (blockNameToken.Kind)
{
default:
// Next token is unexpected.
// ErrorRecovery: if 'lCurly' is present, pretend we saw a closing curly; otherwise, eat the unexpected token.
if (lCurly != null)
{
UngetToken(blockNameToken);
scriptBlockExtent = ExtentOf(startExtent, endExtent);
}
else
{
// If "lCurly == null", then it's a ps1/psm1 file, and thus the extent is the whole file.
scriptBlockExtent = _tokenizer.GetScriptExtent();
}
// Report error about the unexpected token.
ReportError(blockNameToken.Extent, () => ParserStrings.MissingNamedBlocks, blockNameToken.Text);
goto return_script_block_ast;
case TokenKind.RCurly:
case TokenKind.EndOfInput:
// If the next token is RCurly or <eof>, handle it in 'CompleteScriptBlockBody'.
UngetToken(blockNameToken);
extent = ExtentOf(startExtent, endExtent);
goto finished_named_block_list;
case TokenKind.Dynamicparam:
@ -1687,11 +1709,9 @@ namespace System.Management.Automation.Language
SkipNewlinesAndSemicolons();
}
finished_named_block_list:
IScriptExtent scriptBlockExtent;
extent = ExtentOf(startExtent, endExtent);
CompleteScriptBlockBody(lCurly, ref extent, out scriptBlockExtent);
return_script_block_ast:
return new ScriptBlockAst(scriptBlockExtent, usingStatements, paramBlockAst, beginBlock, processBlock, endBlock,
dynamicParamBlock);
}

View file

@ -493,6 +493,9 @@ The correct form is: foreach ($a in $b) {...}</value>
<data name="DuplicateScriptCommandClause" xml:space="preserve">
<value>Script command clause '{0}' has already been defined.</value>
</data>
<data name="MissingNamedBlocks" xml:space="preserve">
<value>unexpected token '{0}', expected 'begin', 'process', 'end', or 'dynamicparam'.</value>
</data>
<data name="MissingEndCurlyBrace" xml:space="preserve">
<value>Missing closing '}' in statement block or type definition.</value>
</data>

View file

@ -915,4 +915,20 @@ foo``u{2195}abc
# Issue #2780
{ ExecuteCommand "`$herestr=@`"`n'`"'`n`"@" } | Should -Not -Throw
}
It "Throw better error when statement should be put in named blocks - <name>" -TestCases @(
@{ script = "Function foo { [CmdletBinding()] param() DynamicParam {} Hi"; name = "function" }
@{ script = "{ begin {} Hi"; name = "script-block" }
@{ script = "begin {} Hi"; name = "script-file" }
) {
param($script)
$err = { ExecuteCommand $script } | Should -Throw -ErrorId "ParseException" -PassThru
$err.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId | Should -BeExactly "MissingNamedBlocks"
}
It "IncompleteParseException should be thrown when only ending curly is missing" {
$err = { ExecuteCommand "Function foo { [CmdletBinding()] param() DynamicParam {} " } | Should -Throw -ErrorId "IncompleteParseException" -PassThru
$err.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId | Should -BeExactly "MissingEndCurlyBrace"
}
}