-
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
Move to more consistent patterns in the parser. #65724
Conversation
if (this.CurrentToken.Kind == SyntaxKind.OperatorKeyword) | ||
{ | ||
return null; | ||
} |
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.
unnecessary. the very next check bails if we don't have an identifiertoken, so if we have an operatorkeyword, that would always bail.
|
||
if (result.IsMissing && | ||
(this.CurrentToken.Kind != SyntaxKind.CommaToken && this.CurrentToken.Kind != SyntaxKind.GreaterThanToken) && | ||
((nextTokenKind = this.PeekToken(1).Kind) == SyntaxKind.CommaToken || nextTokenKind == SyntaxKind.GreaterThanToken)) | ||
(this.PeekToken(1).Kind is SyntaxKind.CommaToken or SyntaxKind.GreaterThanToken)) |
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.
this is so much cleaner. locals being assigned halfway through an expr to read later is not good :)
@@ -7227,6 +7197,7 @@ private SyntaxToken EatNullableQualifierIfApplicable(ParseTypeMode mode) | |||
Debug.Assert(this.CurrentToken.Kind == SyntaxKind.QuestionToken); | |||
using var resetPoint = this.GetDisposableResetPoint(resetOnDispose: false); | |||
|
|||
|
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.
@@ -10945,29 +10911,31 @@ private ExpressionSyntax ParseTermWithoutPostfix(Precedence precedence) | |||
return this.AddError(this.CreateMissingIdentifierName(), ErrorCode.ERR_InvalidExprTerm, this.CurrentToken.Text); | |||
} | |||
case SyntaxKind.IdentifierToken: | |||
if (this.IsTrueIdentifier()) | |||
{ |
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.
braces are to prevent some conflicts with pattern name clashes in a switch statement.
@jjonescz @RikkiGibson @333fred ptal :) |
@@ -4774,7 +4693,7 @@ private void ParseParameterModifiers(SyntaxListBuilder modifiers, bool isFunctio | |||
this.ParseVariableDeclarators(type, flags: VariableFlags.LocalOrField, variables: variables, parentKind: parentKind); | |||
|
|||
// Make 'scoped' part of the type when it is the last token in the modifiers list | |||
if (modifiers.Count != 0 && modifiers[modifiers.Count - 1] is SyntaxToken { Kind: SyntaxKind.ScopedKeyword } scopedKeyword) | |||
if (modifiers is [.., SyntaxToken { Kind: SyntaxKind.ScopedKeyword } scopedKeyword]) |
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.
Yaay patterns.
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.
Done review pass.
@@ -7111,8 +6995,11 @@ bool canBeNullableType() | |||
if (mode == ParseTypeMode.DefinitePattern) | |||
return true; // Permit nullable type parsing and report while binding for a better error message | |||
if (mode == ParseTypeMode.NewExpression && type.Kind == SyntaxKind.TupleType && | |||
this.PeekToken(1).Kind != SyntaxKind.OpenParenToken && this.PeekToken(1).Kind != SyntaxKind.OpenBraceToken) | |||
this.PeekToken(1).Kind is not SyntaxKind.OpenParenToken and not SyntaxKind.OpenBraceToken) | |||
{ |
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.
Most of the file you've removed these, but here you added them?
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.
so thsi is a requirement of .net style/formatting. you can only have a single-line body without braces if the condition is also single-line. i can remove, but i figured while i was here i should address it.
} | ||
|
||
return _syntaxFactory.JoinClause(@join, type, name, @in, inExpression, @on, leftExpression, @equals, rightExpression, joinInto); | ||
return _syntaxFactory.JoinClause( |
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 would prefer these using named parameters please, reading this is much more difficult than the original version with local names.
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.
will do!
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.
done.
hey @RikkiGibson could i get eyes on this? |
token = this.AddError(token, ErrorCode.ERR_MemberNeedsType); | ||
var voidType = _syntaxFactory.PredefinedType(token); | ||
var voidType = _syntaxFactory.PredefinedType( | ||
this.AddError(SyntaxFactory.MissingToken(SyntaxKind.VoidKeyword), ErrorCode.ERR_MemberNeedsType)); |
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 am wondering if a syntactically simpler helper for creating a missing token with a certain error on it would be desirable here and in many other places. For example: this.CreateMissingToken(SyntaxKind.VoidKeyword, ErrorCode.MemberNeedsType)
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.
that would make a ton of sense, and i would def be in support of helpers for common patterns like this.
@@ -6270,7 +6167,7 @@ private bool IsOpenName() | |||
separator = ConvertToMissingWithTrailingTrivia(separator, SyntaxKind.DotToken); | |||
} | |||
|
|||
if (isEvent && this.CurrentToken.Kind != SyntaxKind.OpenBraceToken && this.CurrentToken.Kind != SyntaxKind.SemicolonToken) | |||
if (isEvent && this.CurrentToken.Kind is not SyntaxKind.OpenBraceToken and not SyntaxKind.SemicolonToken) |
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 wouldn't mind seeing these De Morgan'd like this.CurrentToken.Kind is not (SyntaxKind.OpenBraceToken or SyntaxKind.SemicolonToken)
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 was on the fence. Parenthesized patterns don't quite feel natural to me just yet. And i thought this was nice for preserving the same exact type of check we previously had. e.g. it was &&
and !=
before, so makign that and
and not
seemed the least contentious.
this.CurrentToken.Kind == SyntaxKind.OpenBracketToken || // array type | ||
this.CurrentToken.Kind == SyntaxKind.OpenBraceToken; // object initializer | ||
this.CurrentToken.Kind is SyntaxKind.OpenParenToken or // ctor parameters | ||
SyntaxKind.OpenBracketToken or // array type |
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 personally would not do this (inserting extra spaces in order to make certain tokens align across lines).
In fact, this is something the format analyzer forbids in other cases. e.g.
roslyn/src/Workspaces/Core/Portable/Editing/DeclarationModifiers.cs
Lines 192 to 216 in d73d31c
[Flags] | |
private enum Modifiers | |
{ | |
#pragma warning disable format | |
None = 0, | |
Static = 1 << 0, | |
Abstract = 1 << 1, | |
New = 1 << 2, | |
Unsafe = 1 << 3, | |
ReadOnly = 1 << 4, | |
Virtual = 1 << 5, | |
Override = 1 << 6, | |
Sealed = 1 << 7, | |
Const = 1 << 8, | |
WithEvents = 1 << 9, | |
Partial = 1 << 10, | |
Async = 1 << 11, | |
WriteOnly = 1 << 12, | |
Ref = 1 << 13, | |
Volatile = 1 << 14, | |
Extern = 1 << 15, | |
Required = 1 << 16, | |
File = 1 << 17, | |
#pragma warning restore format | |
} |
I would much rather see us simply insert a line break + indent before the token where we desire the alignment.
return this.CurrentToken.Kind is
SyntaxKind.OpenParenToken or
SyntaxKind.OpenBracketToken or
SyntaxKind.OpenBraceToken;
I prefer even more to put the operator token at the start of the line. SyntaxKind will not strictly align in this case (if we used an and
or not
operator in some places, for example), but the visual pop of seeing the smaller operator token at the start of the line seems better for skimmability, in my opinion.
return this.CurrentToken.Kind
is SyntaxKind.OpenParenToken
or SyntaxKind.OpenBracketToken
or SyntaxKind.OpenBraceToken;
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 can do that. i checked with IDE at one point if we had a view on where was best for operators, and currently there's no consistency from the team. so we'ved decided to not be opinionated there.
|
||
case SyntaxKind.ExclamationToken: | ||
expr = _syntaxFactory.PostfixUnaryExpression(SyntaxKind.SuppressNullableWarningExpression, expr, this.EatToken()); | ||
break; | ||
continue; |
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.
It looks like using continue here instead of break is just to improve clarity? We used to jump to the end of the switch statement and then hit the top of the next loop iteration, but now we just hit the top of the next loop iteration?
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.
correct. IMO 'continue' is better for clarity. 'break' both has the issue of being confusing (am i breaking the loop? or am i in a switch?), and needing the reader to then need to see what happens at the end of hte loop. 'continue' perfect describes what is happening, and doesn't require forward reading.
this.EatTokenAsKind(SyntaxKind.IdentifierToken) : | ||
this.ParseIdentifierToken(); | ||
var identifier = (this.CurrentToken.Kind != SyntaxKind.IdentifierToken && this.PeekToken(1).Kind == SyntaxKind.EqualsGreaterThanToken) | ||
? this.EatTokenAsKind(SyntaxKind.IdentifierToken) |
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 personally find it strange that we like to put the ?:
tokens at the start of the line, but we like to put the is
/or
tokens at the end of the line.
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.
Jah. This is the opinionated IDE style we have. We have a formatting rule for this as well, but it (like most things) is turned off in teh compiler layer :)
Definitely review with whitespace off.