-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix parsing certain postfix expressions with top level collection literals #68787
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10609,6 +10609,289 @@ public void MemberAccess22A() | |
EOF(); | ||
} | ||
|
||
[Fact] | ||
public void MemberAccess23() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider naming these tests something like PostFixOperator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will fix in next pr |
||
{ | ||
UsingTree(""" | ||
class Program | ||
{ | ||
static void Main() | ||
{ | ||
[]++; | ||
} | ||
} | ||
"""); | ||
|
||
N(SyntaxKind.CompilationUnit); | ||
{ | ||
N(SyntaxKind.ClassDeclaration); | ||
{ | ||
N(SyntaxKind.ClassKeyword); | ||
N(SyntaxKind.IdentifierToken, "Program"); | ||
N(SyntaxKind.OpenBraceToken); | ||
N(SyntaxKind.MethodDeclaration); | ||
{ | ||
N(SyntaxKind.StaticKeyword); | ||
N(SyntaxKind.PredefinedType); | ||
{ | ||
N(SyntaxKind.VoidKeyword); | ||
} | ||
N(SyntaxKind.IdentifierToken, "Main"); | ||
N(SyntaxKind.ParameterList); | ||
{ | ||
N(SyntaxKind.OpenParenToken); | ||
N(SyntaxKind.CloseParenToken); | ||
} | ||
N(SyntaxKind.Block); | ||
{ | ||
N(SyntaxKind.OpenBraceToken); | ||
N(SyntaxKind.ExpressionStatement); | ||
{ | ||
N(SyntaxKind.PostIncrementExpression); | ||
{ | ||
N(SyntaxKind.CollectionExpression); | ||
{ | ||
N(SyntaxKind.OpenBracketToken); | ||
N(SyntaxKind.CloseBracketToken); | ||
} | ||
N(SyntaxKind.PlusPlusToken); | ||
} | ||
N(SyntaxKind.SemicolonToken); | ||
} | ||
N(SyntaxKind.CloseBraceToken); | ||
} | ||
} | ||
N(SyntaxKind.CloseBraceToken); | ||
} | ||
N(SyntaxKind.EndOfFileToken); | ||
} | ||
EOF(); | ||
} | ||
|
||
[Fact] | ||
public void MemberAccess23A() | ||
{ | ||
UsingTree(""" | ||
[]++; | ||
"""); | ||
|
||
N(SyntaxKind.CompilationUnit); | ||
{ | ||
N(SyntaxKind.GlobalStatement); | ||
{ | ||
N(SyntaxKind.ExpressionStatement); | ||
{ | ||
N(SyntaxKind.PostIncrementExpression); | ||
{ | ||
N(SyntaxKind.CollectionExpression); | ||
{ | ||
N(SyntaxKind.OpenBracketToken); | ||
N(SyntaxKind.CloseBracketToken); | ||
} | ||
N(SyntaxKind.PlusPlusToken); | ||
} | ||
N(SyntaxKind.SemicolonToken); | ||
} | ||
} | ||
N(SyntaxKind.EndOfFileToken); | ||
} | ||
EOF(); | ||
} | ||
|
||
[Fact] | ||
public void MemberAccess24() | ||
{ | ||
UsingTree(""" | ||
class Program | ||
{ | ||
static void Main() | ||
{ | ||
[]--; | ||
} | ||
} | ||
"""); | ||
|
||
N(SyntaxKind.CompilationUnit); | ||
{ | ||
N(SyntaxKind.ClassDeclaration); | ||
{ | ||
N(SyntaxKind.ClassKeyword); | ||
N(SyntaxKind.IdentifierToken, "Program"); | ||
N(SyntaxKind.OpenBraceToken); | ||
N(SyntaxKind.MethodDeclaration); | ||
{ | ||
N(SyntaxKind.StaticKeyword); | ||
N(SyntaxKind.PredefinedType); | ||
{ | ||
N(SyntaxKind.VoidKeyword); | ||
} | ||
N(SyntaxKind.IdentifierToken, "Main"); | ||
N(SyntaxKind.ParameterList); | ||
{ | ||
N(SyntaxKind.OpenParenToken); | ||
N(SyntaxKind.CloseParenToken); | ||
} | ||
N(SyntaxKind.Block); | ||
{ | ||
N(SyntaxKind.OpenBraceToken); | ||
N(SyntaxKind.ExpressionStatement); | ||
{ | ||
N(SyntaxKind.PostDecrementExpression); | ||
{ | ||
N(SyntaxKind.CollectionExpression); | ||
{ | ||
N(SyntaxKind.OpenBracketToken); | ||
N(SyntaxKind.CloseBracketToken); | ||
} | ||
N(SyntaxKind.MinusMinusToken); | ||
} | ||
N(SyntaxKind.SemicolonToken); | ||
} | ||
N(SyntaxKind.CloseBraceToken); | ||
} | ||
} | ||
N(SyntaxKind.CloseBraceToken); | ||
} | ||
N(SyntaxKind.EndOfFileToken); | ||
} | ||
EOF(); | ||
} | ||
|
||
[Fact] | ||
public void MemberAccess24A() | ||
{ | ||
UsingTree(""" | ||
[]--; | ||
"""); | ||
|
||
N(SyntaxKind.CompilationUnit); | ||
{ | ||
N(SyntaxKind.GlobalStatement); | ||
{ | ||
N(SyntaxKind.ExpressionStatement); | ||
{ | ||
N(SyntaxKind.PostDecrementExpression); | ||
{ | ||
N(SyntaxKind.CollectionExpression); | ||
{ | ||
N(SyntaxKind.OpenBracketToken); | ||
N(SyntaxKind.CloseBracketToken); | ||
} | ||
N(SyntaxKind.MinusMinusToken); | ||
} | ||
N(SyntaxKind.SemicolonToken); | ||
} | ||
} | ||
N(SyntaxKind.EndOfFileToken); | ||
} | ||
EOF(); | ||
} | ||
|
||
[Fact] | ||
public void MemberAccess25() | ||
{ | ||
UsingTree(""" | ||
class Program | ||
{ | ||
static void Main() | ||
{ | ||
[]->Goo(); | ||
} | ||
} | ||
"""); | ||
|
||
N(SyntaxKind.CompilationUnit); | ||
{ | ||
N(SyntaxKind.ClassDeclaration); | ||
{ | ||
N(SyntaxKind.ClassKeyword); | ||
N(SyntaxKind.IdentifierToken, "Program"); | ||
N(SyntaxKind.OpenBraceToken); | ||
N(SyntaxKind.MethodDeclaration); | ||
{ | ||
N(SyntaxKind.StaticKeyword); | ||
N(SyntaxKind.PredefinedType); | ||
{ | ||
N(SyntaxKind.VoidKeyword); | ||
} | ||
N(SyntaxKind.IdentifierToken, "Main"); | ||
N(SyntaxKind.ParameterList); | ||
{ | ||
N(SyntaxKind.OpenParenToken); | ||
N(SyntaxKind.CloseParenToken); | ||
} | ||
N(SyntaxKind.Block); | ||
{ | ||
N(SyntaxKind.OpenBraceToken); | ||
N(SyntaxKind.ExpressionStatement); | ||
{ | ||
N(SyntaxKind.InvocationExpression); | ||
{ | ||
N(SyntaxKind.PointerMemberAccessExpression); | ||
{ | ||
N(SyntaxKind.CollectionExpression); | ||
{ | ||
N(SyntaxKind.OpenBracketToken); | ||
N(SyntaxKind.CloseBracketToken); | ||
} | ||
N(SyntaxKind.MinusGreaterThanToken); | ||
N(SyntaxKind.IdentifierName); | ||
{ | ||
N(SyntaxKind.IdentifierToken, "Goo"); | ||
} | ||
} | ||
N(SyntaxKind.ArgumentList); | ||
{ | ||
N(SyntaxKind.OpenParenToken); | ||
N(SyntaxKind.CloseParenToken); | ||
} | ||
} | ||
N(SyntaxKind.SemicolonToken); | ||
} | ||
N(SyntaxKind.CloseBraceToken); | ||
} | ||
} | ||
N(SyntaxKind.CloseBraceToken); | ||
} | ||
N(SyntaxKind.EndOfFileToken); | ||
} | ||
EOF(); | ||
} | ||
|
||
[Fact] | ||
public void MemberAccess25A() | ||
{ | ||
UsingTree(""" | ||
[]->Goo; | ||
"""); | ||
|
||
N(SyntaxKind.CompilationUnit); | ||
{ | ||
N(SyntaxKind.GlobalStatement); | ||
{ | ||
N(SyntaxKind.ExpressionStatement); | ||
{ | ||
N(SyntaxKind.PointerMemberAccessExpression); | ||
{ | ||
N(SyntaxKind.CollectionExpression); | ||
{ | ||
N(SyntaxKind.OpenBracketToken); | ||
N(SyntaxKind.CloseBracketToken); | ||
} | ||
N(SyntaxKind.MinusGreaterThanToken); | ||
N(SyntaxKind.IdentifierName); | ||
{ | ||
N(SyntaxKind.IdentifierToken, "Goo"); | ||
} | ||
} | ||
N(SyntaxKind.SemicolonToken); | ||
} | ||
} | ||
N(SyntaxKind.EndOfFileToken); | ||
} | ||
EOF(); | ||
} | ||
|
||
[Fact] | ||
public void AttributeOnTopLevelFunction1() | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5512,14 +5512,18 @@ void Goo(int i) | |
[Fact] | ||
public void AttributeOnExpressionStatement_PrefixUnary() | ||
{ | ||
var test = UsingTree(@" | ||
class C | ||
{ | ||
void Goo(int i) | ||
{ | ||
[A]++i; | ||
} | ||
}"); | ||
var test = UsingTree(""" | ||
class C | ||
{ | ||
void Goo(int i) | ||
{ | ||
[A]++i; | ||
} | ||
} | ||
""", | ||
// (5,14): error CS1002: ; expected | ||
// [A]++i; | ||
Diagnostic(ErrorCode.ERR_SemicolonExpected, "i").WithLocation(5, 14)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this was an existing error recovery case that i added a few years back (recovering when attributes were put in incorrect places). It's still an error after this pr, just one that views the above as an invalid operation on a collection-expr, not an invalid attribute on an expression statement. Trying to detect this case and keep the old parsing isn't worth it IMO. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, I was just about to comment and say that this needed to be updated. |
||
|
||
N(SyntaxKind.CompilationUnit); | ||
{ | ||
|
@@ -5553,25 +5557,29 @@ void Goo(int i) | |
N(SyntaxKind.OpenBraceToken); | ||
N(SyntaxKind.ExpressionStatement); | ||
{ | ||
N(SyntaxKind.AttributeList); | ||
N(SyntaxKind.PostIncrementExpression); | ||
{ | ||
N(SyntaxKind.OpenBracketToken); | ||
N(SyntaxKind.Attribute); | ||
N(SyntaxKind.CollectionExpression); | ||
{ | ||
N(SyntaxKind.IdentifierName); | ||
N(SyntaxKind.OpenBracketToken); | ||
N(SyntaxKind.ExpressionElement); | ||
{ | ||
N(SyntaxKind.IdentifierToken, "A"); | ||
N(SyntaxKind.IdentifierName); | ||
{ | ||
N(SyntaxKind.IdentifierToken, "A"); | ||
} | ||
} | ||
N(SyntaxKind.CloseBracketToken); | ||
} | ||
N(SyntaxKind.CloseBracketToken); | ||
N(SyntaxKind.PlusPlusToken); | ||
} | ||
N(SyntaxKind.PreIncrementExpression); | ||
M(SyntaxKind.SemicolonToken); | ||
} | ||
N(SyntaxKind.ExpressionStatement); | ||
{ | ||
N(SyntaxKind.IdentifierName); | ||
{ | ||
N(SyntaxKind.PlusPlusToken); | ||
N(SyntaxKind.IdentifierName); | ||
{ | ||
N(SyntaxKind.IdentifierToken, "i"); | ||
} | ||
N(SyntaxKind.IdentifierToken, "i"); | ||
} | ||
N(SyntaxKind.SemicolonToken); | ||
} | ||
|
@@ -5585,9 +5593,18 @@ void Goo(int i) | |
EOF(); | ||
|
||
CreateCompilation(test).GetDiagnostics().Verify( | ||
// (6,9): error CS7014: Attributes are not valid in this context. | ||
// (5,9): error CS8652: The feature 'collection literals' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. | ||
// [A]++i; | ||
Diagnostic(ErrorCode.ERR_AttributesNotAllowed, "[A]").WithLocation(6, 9)); | ||
Diagnostic(ErrorCode.ERR_FeatureInPreview, "[").WithArguments("collection literals").WithLocation(5, 9), | ||
// (5,10): error CS0103: The name 'A' does not exist in the current context | ||
// [A]++i; | ||
Diagnostic(ErrorCode.ERR_NameNotInContext, "A").WithArguments("A").WithLocation(5, 10), | ||
// (5,14): error CS1002: ; expected | ||
// [A]++i; | ||
Diagnostic(ErrorCode.ERR_SemicolonExpected, "i").WithLocation(5, 14), | ||
// (5,14): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement | ||
// [A]++i; | ||
Diagnostic(ErrorCode.ERR_IllegalStatement, "i").WithLocation(5, 14)); | ||
} | ||
|
||
[Fact] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are we going to remember to make a corresponding change here if another postfix operator is ever added to the language? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add comment