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.
This commit is contained in:
Ilya
2017-02-13 16:45:00 -08:00
committed by Jason Shirk
parent ca5fc9c5a8
commit a16fead0a5
6 changed files with 16 additions and 12 deletions
@@ -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<Func<string>>)(() => ParserStrings.IncompletePropertyAssignmentBlock)
: (Expression<Func<string>>)(() => ParserStrings.IncompleteHashLiteral);
ReportIncompleteInput(keyValuePairs.Any() ? After(keyValuePairs.Last().Item2) : After(atCurlyToken), rCurly.Extent, errorMessageExpression);
: (Expression<Func<string>>)(() => ParserStrings.MissingEndCurlyBrace);
ReportIncompleteInput(After(atCurlyToken), rCurly.Extent, errorMessageExpression);
endExtent = Before(rCurly);
}
else
@@ -6394,7 +6394,7 @@ namespace System.Management.Automation.Language
? (() => (ParserStrings.MissingEqualsInPropertyAssignmentBlock))
: (Expression<Func<string>>)(() => 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));
}
@@ -347,9 +347,6 @@ Possible matches are</value>
<data name="MissingExpressionInNamedArgument" xml:space="preserve">
<value>Missing statement after '=' in named argument.</value>
</data>
<data name="IncompleteHashLiteral" xml:space="preserve">
<value>The hash literal was incomplete.</value>
</data>
<data name="MissingPropertyTerminator" xml:space="preserve">
<value>Missing ';' or end-of-line in property definition.</value>
</data>
@@ -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" {
@@ -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'
}
@@ -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
}
@@ -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
}
}
Describe 'Hash Expression parsing' -Tags "CI" {
ShouldBeParseError '@{ a=1;b=2;c=3;' MissingEndCurlyBrace 2
}