From 6c66fa418e3c154b715769307300046aa829515a Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Tue, 5 Jun 2018 00:53:54 -0700 Subject: [PATCH 1/4] [Feature] Fix parser to continue parsing key-value pairs after an If-Statement value in a HashExpression --- .../engine/parser/Parser.cs | 18 ++++++++++++++++-- .../LanguageAndParser.TestFollowup.Tests.ps1 | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/System.Management.Automation/engine/parser/Parser.cs b/src/System.Management.Automation/engine/parser/Parser.cs index ebdae013f2f..7c332bb8e24 100644 --- a/src/System.Management.Automation/engine/parser/Parser.cs +++ b/src/System.Management.Automation/engine/parser/Parser.cs @@ -2411,6 +2411,16 @@ private StatementAst IfStatementRule(Token ifToken) clauses.Add(new IfClause(condition, body)); + // Save a restore point here. In case there is no 'elseif' or 'else' following, + // we should resync back here to preserve the possible new lines. The new lines + // could be important for the following parsing. For example, in case we are in + // a HashExpression, a new line might be needed for parsing the key-value that + // is following the if statement: + // @{ + // a = if (1) {} + // b = 10 + // } + var restorePoint = PeekToken(); SkipNewlines(); keyword = PeekToken(); @@ -2419,8 +2429,7 @@ private StatementAst IfStatementRule(Token ifToken) SkipToken(); continue; } - - if (keyword.Kind == TokenKind.Else) + else if (keyword.Kind == TokenKind.Else) { SkipToken(); SkipNewlines(); @@ -2436,6 +2445,11 @@ private StatementAst IfStatementRule(Token ifToken) return new ErrorStatementAst(ExtentOf(ifToken, keyword), componentAsts); } } + else + { + // There is no 'elseif' or 'else' following, so resync back to the possible new lines. + Resync(restorePoint); + } break; } diff --git a/test/powershell/Language/Parser/LanguageAndParser.TestFollowup.Tests.ps1 b/test/powershell/Language/Parser/LanguageAndParser.TestFollowup.Tests.ps1 index 8860d492c24..4a48c9ead9e 100644 --- a/test/powershell/Language/Parser/LanguageAndParser.TestFollowup.Tests.ps1 +++ b/test/powershell/Language/Parser/LanguageAndParser.TestFollowup.Tests.ps1 @@ -212,3 +212,22 @@ Describe "Members of System.Type" -Tags "CI" { [MyType].ImplementedInterfaces | Should -Be System.Collections.IEnumerable } } + +Describe "Hash expression with if statement as value" -Tags "CI" { + It "Key-value pairs after an if-statement-value in a HashExpression should continue to be parsed" { + $result = @{ + a = if (1) {'a'} + b = 'b' + c = if (0) {2} elseif (1) {'c'} + d = 'd' + e = if (0) {2} else {'e'} + f = 'f' + } + $result['a'] | Should -BeExactly 'a' + $result['b'] | Should -BeExactly 'b' + $result['c'] | Should -BeExactly 'c' + $result['d'] | Should -BeExactly 'd' + $result['e'] | Should -BeExactly 'e' + $result['f'] | Should -BeExactly 'f' + } +} From 965fb107989a1876b1a54fa147f17113612218ff Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Tue, 5 Jun 2018 12:17:52 -0700 Subject: [PATCH 2/4] [Feature] Minor udpate --- src/System.Management.Automation/engine/parser/Parser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/engine/parser/Parser.cs b/src/System.Management.Automation/engine/parser/Parser.cs index 7c332bb8e24..ea36987b7d3 100644 --- a/src/System.Management.Automation/engine/parser/Parser.cs +++ b/src/System.Management.Automation/engine/parser/Parser.cs @@ -2420,7 +2420,7 @@ private StatementAst IfStatementRule(Token ifToken) // a = if (1) {} // b = 10 // } - var restorePoint = PeekToken(); + int restorePoint = _ungotToken == null ? _tokenizer.GetRestorePoint() : _ungotToken.Extent.StartOffset; SkipNewlines(); keyword = PeekToken(); From 2b77af6acacf211fd23fd286fc6bf1cad4450c97 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Tue, 5 Jun 2018 16:19:24 -0700 Subject: [PATCH 3/4] Address Jason's comment --- .../LanguageAndParser.TestFollowup.Tests.ps1 | 49 +++++++++++++++---- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/test/powershell/Language/Parser/LanguageAndParser.TestFollowup.Tests.ps1 b/test/powershell/Language/Parser/LanguageAndParser.TestFollowup.Tests.ps1 index 4a48c9ead9e..e4242987eb9 100644 --- a/test/powershell/Language/Parser/LanguageAndParser.TestFollowup.Tests.ps1 +++ b/test/powershell/Language/Parser/LanguageAndParser.TestFollowup.Tests.ps1 @@ -214,20 +214,51 @@ Describe "Members of System.Type" -Tags "CI" { } Describe "Hash expression with if statement as value" -Tags "CI" { - It "Key-value pairs after an if-statement-value in a HashExpression should continue to be parsed" { - $result = @{ + BeforeAll { + # With no extra new lines after if-statement + $hash1 = @{ a = if (1) {'a'} b = 'b' c = if (0) {2} elseif (1) {'c'} d = 'd' - e = if (0) {2} else {'e'} + e = if (0) {2} elseif (0) {2} else {'e'} f = 'f' + g = if (0) {2} else {'g'} + h = 'h' } - $result['a'] | Should -BeExactly 'a' - $result['b'] | Should -BeExactly 'b' - $result['c'] | Should -BeExactly 'c' - $result['d'] | Should -BeExactly 'd' - $result['e'] | Should -BeExactly 'e' - $result['f'] | Should -BeExactly 'f' + + # With extra new lines after if-statement + $hash2 = @{ + a = if (1) {'a'} + + b = 'b' + c = if (0) {2} elseif (1) {'c'} + + d = 'd' + e = if (0) {2} elseif (0) {2} else {'e'} + + f = 'f' + g = if (0) {2} else {'g'} + + h = 'h' + } + + $testCases = @( + @{ name = "No extra new lines"; hash = $hash1 } + @{ name = "With extra new lines"; hash = $hash2 } + ) + } + + It "Key-value pairs after an if-statement-value in a HashExpression should continue to be parsed - " -TestCases $testCases { + param($hash) + + $hash['a'] | Should -BeExactly 'a' + $hash['b'] | Should -BeExactly 'b' + $hash['c'] | Should -BeExactly 'c' + $hash['d'] | Should -BeExactly 'd' + $hash['e'] | Should -BeExactly 'e' + $hash['f'] | Should -BeExactly 'f' + $hash['g'] | Should -BeExactly 'g' + $hash['h'] | Should -BeExactly 'h' } } From b5a67ddcc27ee9519e4086b8edd68cce74fab10f Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Tue, 5 Jun 2018 17:21:57 -0700 Subject: [PATCH 4/4] Address Rob's comment --- .../LanguageAndParser.TestFollowup.Tests.ps1 | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/powershell/Language/Parser/LanguageAndParser.TestFollowup.Tests.ps1 b/test/powershell/Language/Parser/LanguageAndParser.TestFollowup.Tests.ps1 index e4242987eb9..da50b2e5541 100644 --- a/test/powershell/Language/Parser/LanguageAndParser.TestFollowup.Tests.ps1 +++ b/test/powershell/Language/Parser/LanguageAndParser.TestFollowup.Tests.ps1 @@ -243,9 +243,50 @@ Describe "Hash expression with if statement as value" -Tags "CI" { h = 'h' } + # With expanded if-statement + $hash3 = @{ + a = if (1) + { + 'a' + } + b = 'b' + c = if (0) + { + 2 + } + elseif (1) + { + 'c' + } + d = 'd' + e = if (0) + { + 2 + } + elseif (0) + { + 2 + } + else + { + 'e' + } + f = 'f' + g = if (0) + { + 2 + } + else + { + 'g' + } + h = 'h' + } + $testCases = @( @{ name = "No extra new lines"; hash = $hash1 } @{ name = "With extra new lines"; hash = $hash2 } + @{ name = "With expanded if-statement"; hash = $hash3 } ) }