提交 5c9cd2a6 编写于 作者: C CyrusNajmabadi 提交者: Julien Couvreur

Improve error tolerance when parsing invalid implicit arrays. (#24706)

* Improve error tolerance when parsing invalid implicit arrays.

Provide helper for common pattern.

Update test.

* Be resilient to infinite loops.
上级 feee86e2
......@@ -450,19 +450,19 @@ private static bool IsPossibleStartOfTypeDeclaration(SyntaxKind kind)
{
if (body.Members.Count > 0)
{
body.Members[body.Members.Count - 1] = AddTrailingSkippedSyntax(body.Members[body.Members.Count - 1], skippedSyntax);
AddTrailingSkippedSyntax(body.Members, skippedSyntax);
}
else if (body.Attributes.Count > 0)
{
body.Attributes[body.Attributes.Count - 1] = AddTrailingSkippedSyntax(body.Attributes[body.Attributes.Count - 1], skippedSyntax);
AddTrailingSkippedSyntax(body.Attributes, skippedSyntax);
}
else if (body.Usings.Count > 0)
{
body.Usings[body.Usings.Count - 1] = AddTrailingSkippedSyntax(body.Usings[body.Usings.Count - 1], skippedSyntax);
AddTrailingSkippedSyntax(body.Usings, skippedSyntax);
}
else if (body.Externs.Count > 0)
{
body.Externs[body.Externs.Count - 1] = AddTrailingSkippedSyntax(body.Externs[body.Externs.Count - 1], skippedSyntax);
AddTrailingSkippedSyntax(body.Externs, skippedSyntax);
}
else if (openBrace != null)
{
......@@ -3275,7 +3275,7 @@ private enum PostSkipAction
var action = SkipBadTokensWithExpectedKind(isNotExpectedFunction, abortFunction, expected, out lastItemTrailingTrivia);
if (lastItemTrailingTrivia != null)
{
list[list.Count - 1] = AddTrailingSkippedSyntax((CSharpSyntaxNode)list[list.Count - 1], lastItemTrailingTrivia);
AddTrailingSkippedSyntax(list, lastItemTrailingTrivia);
}
trailingTrivia = null;
return action;
......@@ -3299,7 +3299,7 @@ private enum PostSkipAction
var action = SkipBadTokensWithErrorCode(isNotExpectedFunction, abortFunction, error, out lastItemTrailingTrivia);
if (lastItemTrailingTrivia != null)
{
list[list.Count - 1] = AddTrailingSkippedSyntax(list[list.Count - 1], lastItemTrailingTrivia);
AddTrailingSkippedSyntax(list, lastItemTrailingTrivia);
}
trailingTrivia = null;
return action;
......@@ -10600,13 +10600,32 @@ private ImplicitArrayCreationExpressionSyntax ParseImplicitlyTypedArrayCreation(
var commas = _pool.Allocate();
try
{
while (this.CurrentToken.Kind == SyntaxKind.CommaToken)
int lastTokenPosition = -1;
while (IsMakingProgress(ref lastTokenPosition))
{
if (this.IsPossibleExpression())
{
var size = this.AddError(this.ParseExpressionCore(), ErrorCode.ERR_InvalidArray);
if (commas.Count == 0)
{
openBracket = AddTrailingSkippedSyntax(openBracket, size);
}
else
{
AddTrailingSkippedSyntax(commas, size);
}
}
if (this.CurrentToken.Kind == SyntaxKind.CommaToken)
{
commas.Add(this.EatToken());
continue;
}
var closeBracket = this.EatToken(SyntaxKind.CloseBracketToken);
break;
}
var closeBracket = this.EatToken(SyntaxKind.CloseBracketToken);
var initializer = this.ParseArrayInitializer();
return _syntaxFactory.ImplicitArrayCreationExpression(@new, openBracket, commas.ToList(), closeBracket, initializer);
......@@ -10816,7 +10835,7 @@ private ParameterListSyntax ParseLambdaParameterList()
// additional parameters
int tokenProgress = -1;
while(IsMakingProgress(ref tokenProgress))
while (IsMakingProgress(ref tokenProgress))
{
if (this.CurrentToken.Kind == SyntaxKind.CloseParenToken)
{
......
......@@ -829,6 +829,16 @@ protected static SyntaxDiagnosticInfo MakeError(ErrorCode code, params object[]
return SyntaxFirstTokenReplacer.Replace(node, oldToken, newToken, skippedSyntax.FullWidth);
}
protected void AddTrailingSkippedSyntax(SyntaxListBuilder list, GreenNode skippedSyntax)
{
list[list.Count - 1] = AddTrailingSkippedSyntax((CSharpSyntaxNode)list[list.Count - 1], skippedSyntax);
}
protected void AddTrailingSkippedSyntax<TNode>(SyntaxListBuilder<TNode> list, GreenNode skippedSyntax) where TNode : CSharpSyntaxNode
{
list[list.Count - 1] = AddTrailingSkippedSyntax(list[list.Count - 1], skippedSyntax);
}
protected TNode AddTrailingSkippedSyntax<TNode>(TNode node, GreenNode skippedSyntax) where TNode : CSharpSyntaxNode
{
var token = node as SyntaxToken;
......
......@@ -435,27 +435,26 @@ public void F(int dimension)
}
";
string expectedOperationTree = @"
IArrayCreationOperation (OperationKind.ArrayCreation, Type: System.Int32[], IsInvalid) (Syntax: 'new[2]/*</bind>*/')
IArrayCreationOperation (OperationKind.ArrayCreation, Type: ?[], IsInvalid) (Syntax: 'new[2]/*</bind>*/')
Dimension Sizes(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid, IsImplicit) (Syntax: 'new[2]/*</bind>*/')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0, IsInvalid, IsImplicit) (Syntax: 'new[2]/*</bind>*/')
Initializer:
IArrayInitializerOperation (1 elements) (OperationKind.ArrayInitializer, Type: null, IsInvalid) (Syntax: '2]/*</bind>*/')
Element Values(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsInvalid) (Syntax: '2')
IArrayInitializerOperation (0 elements) (OperationKind.ArrayInitializer, Type: null, IsInvalid) (Syntax: '')
Element Values(0)
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS1003: Syntax error, ']' expected
// file.cs(6,31): error CS0178: Invalid rank specifier: expected ',' or ']'
// var x = /*<bind>*/new[2]/*</bind>*/;
Diagnostic(ErrorCode.ERR_SyntaxError, "2").WithArguments("]", "").WithLocation(6, 31),
// CS1514: { expected
Diagnostic(ErrorCode.ERR_InvalidArray, "2").WithLocation(6, 31),
// file.cs(6,44): error CS1514: { expected
// var x = /*<bind>*/new[2]/*</bind>*/;
Diagnostic(ErrorCode.ERR_LbraceExpected, "2").WithLocation(6, 31),
// CS1003: Syntax error, ',' expected
Diagnostic(ErrorCode.ERR_LbraceExpected, ";").WithLocation(6, 44),
// file.cs(6,44): error CS1513: } expected
// var x = /*<bind>*/new[2]/*</bind>*/;
Diagnostic(ErrorCode.ERR_SyntaxError, "]").WithArguments(",", "]").WithLocation(6, 32),
// CS1513: } expected
Diagnostic(ErrorCode.ERR_RbraceExpected, ";").WithLocation(6, 44),
// file.cs(6,27): error CS0826: No best type found for implicitly-typed array
// var x = /*<bind>*/new[2]/*</bind>*/;
Diagnostic(ErrorCode.ERR_RbraceExpected, ";").WithLocation(6, 44)
Diagnostic(ErrorCode.ERR_ImplicitlyTypedArrayNoBestType, "new[2]/*</bind>*/").WithLocation(6, 27)
};
VerifyOperationTreeAndDiagnosticsForTest<ImplicitArrayCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
......
......@@ -271,6 +271,205 @@ public static int Main()
Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments("]", ";"));
}
[Fact, WorkItem(24701, "https://github.com/dotnet/roslyn/issues/24701")]
public void CS0178ERR_InvalidArray_ImplicitArray1()
{
var test = @"
class C {
void Goo() {
var x = new[3] { 1, 2, 3 };
}
}
";
ParseAndValidate(test,
// (4,21): error CS0178: Invalid rank specifier: expected ',' or ']'
// var x = new[3] { 1, 2, 3 };
Diagnostic(ErrorCode.ERR_InvalidArray, "3").WithLocation(4, 21));
}
[Fact, WorkItem(24701, "https://github.com/dotnet/roslyn/issues/24701")]
public void CS0178ERR_InvalidArray_ImplicitArray2()
{
var test = @"
class C {
void Goo() {
var x = new[3,] { 1, 2, 3 };
}
}
";
ParseAndValidate(test,
// (4,21): error CS0178: Invalid rank specifier: expected ',' or ']'
// var x = new[3,] { 1, 2, 3 };
Diagnostic(ErrorCode.ERR_InvalidArray, "3").WithLocation(4, 21));
}
[Fact, WorkItem(24701, "https://github.com/dotnet/roslyn/issues/24701")]
public void CS0178ERR_InvalidArray_ImplicitArray3()
{
var test = @"
class C {
void Goo() {
var x = new[,3] { 1, 2, 3 };
}
}
";
ParseAndValidate(test,
// (4,22): error CS0178: Invalid rank specifier: expected ',' or ']'
// var x = new[,3] { 1, 2, 3 };
Diagnostic(ErrorCode.ERR_InvalidArray, "3").WithLocation(4, 22));
}
[Fact, WorkItem(24701, "https://github.com/dotnet/roslyn/issues/24701")]
public void CS0178ERR_InvalidArray_ImplicitArray4()
{
var test = @"
class C {
void Goo() {
var x = new[,3 { 1, 2, 3 };
}
}
";
ParseAndValidate(test,
// (4,22): error CS0178: Invalid rank specifier: expected ',' or ']'
// var x = new[,3 { 1, 2, 3 };
Diagnostic(ErrorCode.ERR_InvalidArray, "3").WithLocation(4, 22),
// (4,24): error CS1003: Syntax error, ']' expected
// var x = new[,3 { 1, 2, 3 };
Diagnostic(ErrorCode.ERR_SyntaxError, "{").WithArguments("]", "{").WithLocation(4, 24));
}
[Fact, WorkItem(24701, "https://github.com/dotnet/roslyn/issues/24701")]
public void CS0178ERR_InvalidArray_ImplicitArray5()
{
var test = @"
class C {
void Goo() {
var x = new[3 { 1, 2, 3 };
}
}
";
ParseAndValidate(test,
// (4,21): error CS0178: Invalid rank specifier: expected ',' or ']'
// var x = new[3 { 1, 2, 3 };
Diagnostic(ErrorCode.ERR_InvalidArray, "3").WithLocation(4, 21),
// (4,23): error CS1003: Syntax error, ']' expected
// var x = new[3 { 1, 2, 3 };
Diagnostic(ErrorCode.ERR_SyntaxError, "{").WithArguments("]", "{").WithLocation(4, 23));
}
[Fact, WorkItem(24701, "https://github.com/dotnet/roslyn/issues/24701")]
public void CS0178ERR_InvalidArray_ImplicitArray6()
{
var test = @"
class C {
void Goo() {
var x = new[3, { 1, 2, 3 };
}
}
";
ParseAndValidate(test,
// (4,21): error CS0178: Invalid rank specifier: expected ',' or ']'
// var x = new[3, { 1, 2, 3 };
Diagnostic(ErrorCode.ERR_InvalidArray, "3").WithLocation(4, 21),
// (4,24): error CS1003: Syntax error, ']' expected
// var x = new[3, { 1, 2, 3 };
Diagnostic(ErrorCode.ERR_SyntaxError, "{").WithArguments("]", "{").WithLocation(4, 24));
}
[Fact, WorkItem(24701, "https://github.com/dotnet/roslyn/issues/24701")]
public void CS0178ERR_InvalidArray_ImplicitArray7()
{
var test = @"
class C {
void Goo() {
var x = new[3,,] { 1, 2, 3 };
}
}
";
ParseAndValidate(test,
// (4,21): error CS0178: Invalid rank specifier: expected ',' or ']'
// var x = new[3,,] { 1, 2, 3 };
Diagnostic(ErrorCode.ERR_InvalidArray, "3").WithLocation(4, 21));
}
[Fact, WorkItem(24701, "https://github.com/dotnet/roslyn/issues/24701")]
public void CS0178ERR_InvalidArray_ImplicitArray8()
{
var test = @"
class C {
void Goo() {
var x = new[,3,] { 1, 2, 3 };
}
}
";
ParseAndValidate(test,
// (4,22): error CS0178: Invalid rank specifier: expected ',' or ']'
// var x = new[,3,] { 1, 2, 3 };
Diagnostic(ErrorCode.ERR_InvalidArray, "3").WithLocation(4, 22));
}
[Fact, WorkItem(24701, "https://github.com/dotnet/roslyn/issues/24701")]
public void CS0178ERR_InvalidArray_ImplicitArray9()
{
var test = @"
class C {
void Goo() {
var x = new[,,3] { 1, 2, 3 };
}
}
";
ParseAndValidate(test,
// (4,23): error CS0178: Invalid rank specifier: expected ',' or ']'
// var x = new[,,3] { 1, 2, 3 };
Diagnostic(ErrorCode.ERR_InvalidArray, "3").WithLocation(4, 23));
}
[Fact, WorkItem(24701, "https://github.com/dotnet/roslyn/issues/24701")]
public void CS0178ERR_InvalidArray_ImplicitArray10()
{
var test = @"
class C {
void Goo() {
var x = new[3,,3] { 1, 2, 3 };
}
}
";
ParseAndValidate(test,
// (4,21): error CS0178: Invalid rank specifier: expected ',' or ']'
// var x = new[3,,3] { 1, 2, 3 };
Diagnostic(ErrorCode.ERR_InvalidArray, "3").WithLocation(4, 21),
// (4,24): error CS0178: Invalid rank specifier: expected ',' or ']'
// var x = new[3,,3] { 1, 2, 3 };
Diagnostic(ErrorCode.ERR_InvalidArray, "3").WithLocation(4, 24));
}
[Fact, WorkItem(24701, "https://github.com/dotnet/roslyn/issues/24701")]
public void CS0178ERR_InvalidArray_ImplicitArray11()
{
var test = @"
class C {
void Goo() {
var x = new[ { 1, 2, 3 };
}
}
";
ParseAndValidate(test,
// (4,22): error CS1003: Syntax error, ']' expected
// var x = new[ { 1, 2, 3 };
Diagnostic(ErrorCode.ERR_SyntaxError, "{").WithArguments("]", "{").WithLocation(4, 22));
}
[Fact]
public void CS0230ERR_BadForeachDecl()
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册