Simplify representation of AttributeLists/Modifiers on all MemberDecls.#32999
Simplify representation of AttributeLists/Modifiers on all MemberDecls.#32999jcouv merged 42 commits intodotnet:masterfrom
Conversation
| if (node.Modifiers.Count > 0) | ||
| { | ||
| diagnostics.Add(ErrorCode.ERR_BadModifiersOnNamespace, node.Modifiers[0].GetLocation()); | ||
| } |
There was a problem hiding this comment.
this moved from LanguageParser to here. This is how we've dealt with other Namespace errors that were previously syntax errors, that we wanted to move out of hte parser.
| if (attributes.Count > 0) | ||
| { | ||
| namespaceDecl = AddLeadingSkippedSyntax(namespaceDecl, attributes.ToListNode()); | ||
| } |
There was a problem hiding this comment.
no need for skipped syntax (which sucks). We can totally represent this expected sort of case simply in the syntax model.
| abstract Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax.Body.get -> Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode | ||
| abstract Microsoft.CodeAnalysis.CSharp.Syntax.BaseArgumentListSyntax.Arguments.get -> Microsoft.CodeAnalysis.SeparatedSyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax> | ||
| abstract Microsoft.CodeAnalysis.CSharp.Syntax.BaseCrefParameterListSyntax.Parameters.get -> Microsoft.CodeAnalysis.SeparatedSyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterSyntax> | ||
| abstract Microsoft.CodeAnalysis.CSharp.Syntax.BaseFieldDeclarationSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.AttributeListSyntax> |
There was a problem hiding this comment.
@jcouv I'm not sure if htis is the right way to deal with publicapi.shipped.
Here's what happened. types like BaseFieldDeclarationSyntax had 'AttributeLists'. But this abstract method moved down into MemberDeclaration. To ensure that this member still exists in BaseFieldDeclarationSyntax i added an abstract-override. So you'll see that abstract-override added below. This should be source/binary compatible. But it does require updating these files accordingly.
| override Microsoft.CodeAnalysis.CSharp.Syntax.NullableDirectiveTriviaSyntax.IsActive.get -> bool | ||
| override Microsoft.CodeAnalysis.CSharp.Syntax.RangeExpressionSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void | ||
| override Microsoft.CodeAnalysis.CSharp.Syntax.RangeExpressionSyntax.Accept<TResult>(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor<TResult> visitor) -> TResult | ||
| override abstract Microsoft.CodeAnalysis.CSharp.Syntax.BaseFieldDeclarationSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.AttributeListSyntax> |
There was a problem hiding this comment.
here are the abstract overrides corresponding to the members that were removed.
| @@ -1,4 +1,18 @@ | |||
| *REMOVED*static Microsoft.CodeAnalysis.CSharp.LanguageVersionFacts.TryParse(this string version, out Microsoft.CodeAnalysis.CSharp.LanguageVersion result) -> bool | |||
| *REMOVED*abstract Microsoft.CodeAnalysis.CSharp.Syntax.BaseFieldDeclarationSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.AttributeListSyntax> | |||
There was a problem hiding this comment.
@jcouv I'm not sure if htis is the right way to deal with publicapi.shipped.
Here's what happened. types like BaseFieldDeclarationSyntax had 'AttributeLists'. But this abstract method moved down into MemberDeclaration. To ensure that this member still exists in BaseFieldDeclarationSyntax i added an abstract-override. So you'll see that abstract-override added below. This should be source/binary compatible. But it does require updating these files accordingly.
jcouv
left a comment
There was a problem hiding this comment.
Change LGTM modulo some test suggestions (iteration 34). Pinged Neal to confirm the desire to make this change.
|
Thanks for the reviews. Now that i know this works for you guys, i'll beef up the tests :) |
| // [$$ | ||
| // namespace Goo { | ||
| return skippedTokensTriviaSyntax is SkippedTokensTriviaSyntax; | ||
| return false; |
There was a problem hiding this comment.
added bonus. IDE doesn't have to try to infer what's happening from error recovery.
|
I'm marking as "personal" for now, to make room in our query. Ping when tests are added and ready for another look. Thanks! #Closed |
|
@CyrusNajmabadi This PR looks good and is just missing a couple of tests when you get a chance. Thanks! #Closed |
|
@jcouv Yup! I've been a little under the weather. I'll try to get to this in hte next week. Thanks! |
|
@jcouv added a few tiny tests to just hit the new scenarios. |
4c10cfe to
46a8193
Compare
|
@jcouv ? :) |
|
@jcouv I'm champing at the bit for this to go in :D |
|
Awesome, thanks! |
There was a previous parsing change (dotnet#32999) which modified namespace parsing to allow modifiers and attributes on namespaces, to improve error recovery. This PR contained a bug because it didn't move the incremental parsing check to before parsing attributes and modifiers, which should now be included in incremental parsing to prevent changes from being dropped Fixes dotnet#37665, dotnet#37664, dotnet#37663
There was a previous parsing change (#32999) which modified namespace parsing to allow modifiers and attributes on namespaces, to improve error recovery. This PR contained a bug because it didn't move the incremental parsing check to before parsing attributes and modifiers, which should now be included in incremental parsing to prevent changes from being dropped Fixes #37665, #37664, #37663
The current (i.e. prior to this PR) way of representing attributes/modifiers is to specify which nodes they can go on in an adhoc manner. Some member decls specify they take attributes+modifiers, some only attributes, and some take none at all. While this is accurate as per the grammar, it makes for some ungainly APIs and complex use cases.
For example, our parser detects if you write attributes/modifiers for a namespace, but then has no place to put it. Similarly, lots of code in later layers has to write specialized code to get at modifiers/attributelists.
--
This PR attempts to simplify things (taking a page from TypeScript). After this PR, we simply define all member decls as being able to have attributes/modifiers. This means that if we run into attributes/modifiers that aren't grammatically legal, we still have a place to put them. And, later layers can more easily get/change/add these properties easily.
--
This also ties into the goal of pulling errors out of hte parser, since they affect incremental parsing, as well as making it more difficult for later phases to understand what is going on.
--
Todo: