From a16fead0a58dea84b07759d5816ff714dc982011 Mon Sep 17 00:00:00 2001 From: Ilya Date: Tue, 14 Feb 2017 04:45:00 +0400 Subject: [PATCH] Fix error position reporting on classes (#3103) Interactive hosts expect an `IncompleteParseException` to signal that more input is expected. When detecting errors, the parser can report 2 positions: * where the error should be reported * where the error was detected Typically these are the same, so most error reporting methods have a single parameter. For missing braces, the pattern is supposed to be to report the error after the opening brace, but the error is typically detected at the end of the file. There were a few places where we were not consistent in reporting such errors, this PR corrects those places. --- .../engine/parser/Parser.cs | 10 +++++----- .../resources/ParserStrings.resx | 3 --- .../Classes/Scripting.Classes.BasicParsing.Tests.ps1 | 4 +++- .../Language/Classes/scripting.Classes.using.tests.ps1 | 2 +- .../Language/Classes/scripting.enums.tests.ps1 | 3 ++- test/powershell/Language/Parser/Parsing.Tests.ps1 | 6 +++++- 6 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/System.Management.Automation/engine/parser/Parser.cs b/src/System.Management.Automation/engine/parser/Parser.cs index 6050538c39..0e44b2febe 100644 --- a/src/System.Management.Automation/engine/parser/Parser.cs +++ b/src/System.Management.Automation/engine/parser/Parser.cs @@ -3909,7 +3909,7 @@ namespace System.Management.Automation.Language if (rCurly.Kind != TokenKind.RCurly) { UngetToken(rCurly); - ReportIncompleteInput(lastExtent, () => ParserStrings.MissingEndCurlyBrace); + ReportIncompleteInput(After(lCurly), rCurly.Extent, () => ParserStrings.MissingEndCurlyBrace); } else { @@ -4269,7 +4269,7 @@ namespace System.Management.Automation.Language if (rCurly.Kind != TokenKind.RCurly) { UngetToken(rCurly); - ReportIncompleteInput(After(lastExtent), () => ParserStrings.MissingEndCurlyBrace); + ReportIncompleteInput(After(lCurly), rCurly.Extent, () => ParserStrings.MissingEndCurlyBrace); } var startExtent = customAttributes != null && customAttributes.Count > 0 @@ -6344,8 +6344,8 @@ namespace System.Management.Automation.Language // Note - the error handling function inspects the error message body to extra the ParserStrings property name. It uses this value as the errorid. var errorMessageExpression = parsingSchemaElement ? (Expression>)(() => ParserStrings.IncompletePropertyAssignmentBlock) - : (Expression>)(() => ParserStrings.IncompleteHashLiteral); - ReportIncompleteInput(keyValuePairs.Any() ? After(keyValuePairs.Last().Item2) : After(atCurlyToken), rCurly.Extent, errorMessageExpression); + : (Expression>)(() => ParserStrings.MissingEndCurlyBrace); + ReportIncompleteInput(After(atCurlyToken), rCurly.Extent, errorMessageExpression); endExtent = Before(rCurly); } else @@ -6394,7 +6394,7 @@ namespace System.Management.Automation.Language ? (() => (ParserStrings.MissingEqualsInPropertyAssignmentBlock)) : (Expression>)(() => ParserStrings.MissingEqualsInHashLiteral); ReportError(errorExtent, errorMessageExpression); - SyncOnError(true, TokenKind.RCurly, TokenKind.Semi, TokenKind.NewLine); + SyncOnError(false, TokenKind.RCurly, TokenKind.Semi, TokenKind.NewLine); return new KeyValuePair(key, new ErrorStatementAst(errorExtent)); } diff --git a/src/System.Management.Automation/resources/ParserStrings.resx b/src/System.Management.Automation/resources/ParserStrings.resx index 86e7a42f41..8703429582 100644 --- a/src/System.Management.Automation/resources/ParserStrings.resx +++ b/src/System.Management.Automation/resources/ParserStrings.resx @@ -347,9 +347,6 @@ Possible matches are Missing statement after '=' in named argument. - - The hash literal was incomplete. - Missing ';' or end-of-line in property definition. diff --git a/test/powershell/Language/Classes/Scripting.Classes.BasicParsing.Tests.ps1 b/test/powershell/Language/Classes/Scripting.Classes.BasicParsing.Tests.ps1 index 827083793b..520f49147e 100644 --- a/test/powershell/Language/Classes/Scripting.Classes.BasicParsing.Tests.ps1 +++ b/test/powershell/Language/Classes/Scripting.Classes.BasicParsing.Tests.ps1 @@ -251,7 +251,7 @@ Describe 'Positive Parse Properties Tests' -Tags "CI" { Describe 'Negative Parsing Tests' -Tags "CI" { ShouldBeParseError 'class' MissingNameAfterKeyword 5 ShouldBeParseError 'class foo' MissingTypeBody 9 - ShouldBeParseError 'class foo {' MissingEndCurlyBrace 10 + ShouldBeParseError 'class foo {' MissingEndCurlyBrace 11 ShouldBeParseError 'class foo { [int] }' IncompleteMemberDefinition 17 ShouldBeParseError 'class foo { $private: }' InvalidVariableReference 12 ShouldBeParseError 'class foo { [int]$global: }' InvalidVariableReference 17 @@ -307,6 +307,8 @@ Describe 'Negative Parsing Tests' -Tags "CI" { ShouldBeParseError 'class C { static [int]$i; [void] foo() {$i = 10} }' MissingTypeInStaticPropertyAssignment 40 ShouldBeParseError 'class C : B' MissingTypeBody 11 + + ShouldBeParseError 'Class foo { q(){} w(){}' MissingEndCurlyBrace 11 } Describe 'Negative methods Tests' -Tags "CI" { diff --git a/test/powershell/Language/Classes/scripting.Classes.using.tests.ps1 b/test/powershell/Language/Classes/scripting.Classes.using.tests.ps1 index fadbfee303..b8955df693 100644 --- a/test/powershell/Language/Classes/scripting.Classes.using.tests.ps1 +++ b/test/powershell/Language/Classes/scripting.Classes.using.tests.ps1 @@ -257,7 +257,7 @@ New-Object Foo It "report an error on incomplete using input" { $err = Get-ParseResults "using module @{ModuleName = 'FooWithManifest'; FooWithManifest = 1." # missing closing bracket $err.Count | Should Be 2 - $err[0].ErrorId | Should Be 'IncompleteHashLiteral' + $err[0].ErrorId | Should Be 'MissingEndCurlyBrace' $err[1].ErrorId | Should Be 'RequiresModuleInvalid' } diff --git a/test/powershell/Language/Classes/scripting.enums.tests.ps1 b/test/powershell/Language/Classes/scripting.enums.tests.ps1 index f13b31be47..5f5b37d7a9 100644 --- a/test/powershell/Language/Classes/scripting.enums.tests.ps1 +++ b/test/powershell/Language/Classes/scripting.enums.tests.ps1 @@ -85,7 +85,7 @@ Describe 'Basic enum errors' -Tags "CI" { ShouldBeParseError 'enum foo' MissingTypeBody 8 ShouldBeParseError 'enum foo {' MissingEndCurlyBrace 10 ShouldBeParseError 'enum foo { x = }' ExpectedValueExpression 14 - ShouldBeParseError 'enum foo { x =' ExpectedValueExpression,MissingEndCurlyBrace 14,14 + ShouldBeParseError 'enum foo { x =' ExpectedValueExpression,MissingEndCurlyBrace 14,10 ShouldBeParseError 'enum foo {} enum foo {}' MemberAlreadyDefined 12 ShouldBeParseError 'enum foo { x; x }' MemberAlreadyDefined 14 -SkipAndCheckRuntimeError ShouldBeParseError 'enum foo { X; x }' MemberAlreadyDefined 14 -SkipAndCheckRuntimeError @@ -94,4 +94,5 @@ Describe 'Basic enum errors' -Tags "CI" { ShouldBeParseError 'enum foo { e = [int]::MaxValue + 1 }' EnumeratorValueTooLarge 15 -SkipAndCheckRuntimeError ShouldBeParseError 'enum foo { e = $foo }' EnumeratorValueMustBeConstant 15 -SkipAndCheckRuntimeError ShouldBeParseError 'enum foo { e = "hello" }' CannotConvertValue 15 -SkipAndCheckRuntimeError + ShouldBeParseError 'enum foo { a;b;c;' MissingEndCurlyBrace 10 } diff --git a/test/powershell/Language/Parser/Parsing.Tests.ps1 b/test/powershell/Language/Parser/Parsing.Tests.ps1 index 28453aaa92..cd3f389e79 100644 --- a/test/powershell/Language/Parser/Parsing.Tests.ps1 +++ b/test/powershell/Language/Parser/Parsing.Tests.ps1 @@ -299,4 +299,8 @@ Describe 'expressions parsing' -Tags "CI" { ShouldBeParseError '[ref][ref]$x' ReferenceNeedsToBeByItselfInTypeSequence 5 ShouldBeParseError '[int][ref]$x' ReferenceNeedsToBeLastTypeInTypeConversion 5 ShouldBeParseError '[int][ref]$x = 42' ReferenceNeedsToBeByItselfInTypeConstraint 5 -} \ No newline at end of file +} + +Describe 'Hash Expression parsing' -Tags "CI" { + ShouldBeParseError '@{ a=1;b=2;c=3;' MissingEndCurlyBrace 2 +}