From 9b23e1e1fedd22f63bab41f769dab42d022ae50b Mon Sep 17 00:00:00 2001 From: Ilya Date: Wed, 18 Jan 2017 00:54:43 +0400 Subject: [PATCH] Fix error handling in parsing 'using' statement (#3007) --- .../engine/parser/Parser.cs | 10 ++++++-- .../Classes/scripting.Classes.using.tests.ps1 | 23 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/System.Management.Automation/engine/parser/Parser.cs b/src/System.Management.Automation/engine/parser/Parser.cs index 92b0cc253f..6050538c39 100644 --- a/src/System.Management.Automation/engine/parser/Parser.cs +++ b/src/System.Management.Automation/engine/parser/Parser.cs @@ -4414,8 +4414,11 @@ namespace System.Management.Automation.Language { case TokenKind.EndOfInput: case TokenKind.NewLine: - // Example, using module ,FooBar + // Example: 'using module ,FooBar' + // GetCommandArgument will successfully return an argument for a unary array argument + // but we don't want to allow that syntax with a using statement. case TokenKind.Comma: + case TokenKind.Semi: { ReportIncompleteInput(After(directiveToken), () => ParserStrings.MissingUsingItemName); return new ErrorStatementAst(ExtentOf(usingToken, directiveToken)); @@ -4426,11 +4429,14 @@ namespace System.Management.Automation.Language if (itemAst == null) { ReportError(itemToken.Extent, () => ParserStrings.InvalidValueForUsingItemName, itemToken.Text); + // ErrorRecovery: If there is no identifier, skip whole 'using' line + SyncOnError(true, TokenKind.Semi, TokenKind.NewLine); + return new ErrorStatementAst(ExtentOf(usingToken, itemToken.Extent)); } if (!(itemAst is StringConstantExpressionAst) && (kind != UsingStatementKind.Module || !(itemAst is HashtableAst))) { - ReportError(ExtentOf(usingToken, ExtentFromFirstOf(itemAst, itemToken)), () => ParserStrings.InvalidValueForUsingItemName, itemAst.Extent.Text); + ReportError(ExtentFromFirstOf(itemAst, itemToken), () => ParserStrings.InvalidValueForUsingItemName, itemAst.Extent.Text); return new ErrorStatementAst(ExtentOf(usingToken, ExtentFromFirstOf(itemAst, itemToken))); } diff --git a/test/powershell/Language/Classes/scripting.Classes.using.tests.ps1 b/test/powershell/Language/Classes/scripting.Classes.using.tests.ps1 index 23806d5a43..fadbfee303 100644 --- a/test/powershell/Language/Classes/scripting.Classes.using.tests.ps1 +++ b/test/powershell/Language/Classes/scripting.Classes.using.tests.ps1 @@ -261,6 +261,29 @@ New-Object Foo $err[1].ErrorId | Should Be 'RequiresModuleInvalid' } + It "report an error when 'using module' terminating by NewLine" { + $err = Get-ParseResults "using module" + $err.Count | Should Be 1 + $err[0].ErrorId | Should Be 'MissingUsingItemName' + } + + It "report an error when 'using module' terminating by Semicolon" { + $err = Get-ParseResults "using module; $testvar=1" + $err.Count | Should Be 1 + $err[0].ErrorId | Should Be 'MissingUsingItemName' + } + + It "report an error when a value after 'using module' is a unallowed expression" { + $err = Get-ParseResults "using module )" + $err.Count | Should Be 1 + $err[0].ErrorId | Should Be 'InvalidValueForUsingItemName' + } + + It "report an error when a value after 'using module' is not a valid module name" { + $err = Get-ParseResults "using module 123" + $err.Count | Should Be 1 + $err[0].ErrorId | Should Be 'InvalidValueForUsingItemName' + } } Context 'short name in case of name collision' {