Skip to content
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

Parse attributes on local function declarations #38808

Conversation

RikkiGibson
Copy link
Contributor

@RikkiGibson RikkiGibson commented Sep 23, 2019

Related to #38801

Attributes on local function parameters or type parameters are already parsed as expected but they simply give errors. This PR adds an AttributeLists property to LocalFunctionStatementSyntax and parses the attributes into that property.

@CyrusNajmabadi
Copy link
Member

This PR adds an AttributeLists property to LocalFunctionDeclarationSyntax and parses the attributes into that property.

Definitely a way to go! Alternatively, previously, i made it so that any MemberDeclarationSyntax could have Attributes. If the impl is not too complex here, you might want to consider making it so that any statement could have attributes on it, and that we just bail on them for anything but local functions.

This has hte virtue of embedding them in our syntactic model consistently, and making it much easier to represent in the tree for editing/recovery scenario.

If this is complex, do not do it. BUt def something to maybe consider :)

@@ -7177,8 +7182,9 @@ private bool IsPossibleStatement(bool acceptAccessibilityMods)
case SyntaxKind.InternalKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.PrivateKeyword:
// could be a local function with attributes
case SyntaxKind.OpenBracketToken: // PROTOTYPE reuse this or always allow the OpenBracketToken?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would always allow it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will revisit this when it comes time to remove the prototype comments before merging to master.

@CyrusNajmabadi
Copy link
Member

Looking good!

@RikkiGibson
Copy link
Contributor Author

Thanks for your feedback, will look into adding AttributeLists to StatementSyntax. (instinctively I wonder if that would be a significant amount of churn in LanguageParser?) Would this make it so if we have some error recovery scenario where maybe some local declaration doesn't parse as a local function, but it happens to have attributes, we could give better diagnostics?

@jcouv
Copy link
Member

jcouv commented Sep 24, 2019

I don't think this PR should target master. Will probably need a feature branch.

@RikkiGibson RikkiGibson changed the base branch from master to feature/local-function-attributes September 24, 2019 18:45
@RikkiGibson
Copy link
Contributor Author

I used the wrong naming convention for the base branch 🤦‍♂

@RikkiGibson RikkiGibson changed the base branch from feature/local-function-attributes to features/local-function-attributes September 24, 2019 20:23
@RikkiGibson RikkiGibson reopened this Sep 24, 2019
@RikkiGibson RikkiGibson marked this pull request as ready for review September 25, 2019 17:52
@RikkiGibson RikkiGibson requested a review from a team as a code owner September 25, 2019 17:52
@RikkiGibson RikkiGibson added this to the Compiler.Next milestone Sep 25, 2019
@RikkiGibson
Copy link
Contributor Author

@dotnet/roslyn-compiler Please review

@RikkiGibson RikkiGibson requested a review from a team September 26, 2019 22:46
@RikkiGibson
Copy link
Contributor Author

Could I please get a second review @dotnet/roslyn-compiler

@jaredpar
Copy link
Member

    private VariableDeclaratorSyntax ParseVariableDeclarator(

What happens if an attribute is applied to a standard local variable? Looks like the parser will parse out the attribute but then not attach it to any other node. Won't that cause a consistency issue in the parse tree? Feel like we should have tests for this.


Refers to: src/Compilers/CSharp/Portable/Parser/LanguageParser.cs:4145 in 2c251ee. [](commit_id = 2c251ee, deletion_comment = False)

@jaredpar
Copy link
Member

Review pass complete (iteration 9)


In reply to: 535713832 [](ancestors = 535713832)

@RikkiGibson
Copy link
Contributor Author

We have tests which include an unexpected attribute on a local variable declaration, but I can go into more detail in them to show exactly how to access the unexpected attribute if you’d like.

@jaredpar
Copy link
Member

Where are the tests? If the tests do exist why are they not tripping up the new error you just added about requiring a new version of C#? I would presume the old tests are still using langversion 8.0 hence they should trip up the new error.

Also is there a test where an attribute is used on a local declaration statement that has multiple locals?


In reply to: 536000459 [](ancestors = 536000459)

@RikkiGibson
Copy link
Contributor Author

RikkiGibson commented Sep 27, 2019

I have a few local declaration with attribute parsing tests in here but some already exist such as ParserErrorMessageTests.AttributeInMethodBody.

The LangVersion error is only going to happen if the attribute was on a local function. The diagnostics for putting an attribute on any statement besides LocalFunctionStatement aren't expected to change.

I'm not aware of a test which tries to parse a local variable declaration with multiple declarators and with attributes. If you think that would be useful I can add it.

{
void M()
{
[A] object local1, local2;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What hapens if the attribute is before the second local?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the attribute comes after the type the parser believes it's some kind of bad array declarator.

@RikkiGibson
Copy link
Contributor Author

I ended up sticking with AttributeLists on the LocalFunctionStatement and the main reason is that Modifiers is also declared on LocalFunctionStatement (not inherited) and it feels like the two should be consistent with each other.

@RikkiGibson RikkiGibson merged commit 6865152 into dotnet:features/local-function-attributes Sep 27, 2019
@RikkiGibson RikkiGibson deleted the feature/local-function-attributes branch September 27, 2019 21:58
@CyrusNajmabadi
Copy link
Member

I ended up sticking with AttributeLists on the LocalFunctionStatement and the main reason is that Modifiers is also declared on LocalFunctionStatement (not inherited) and it feels like the two should be consistent with each other.

I agree. Though note this is something that can change in the future. Fields can "move up" the inheritance hierachy without problems. As i mentioned before, i did this for modifiers/attributes on MemberDeclarationSyntax.

If you're ok with it, i may try to make the attributes-approach more generalized here in your branch.

@RikkiGibson
Copy link
Contributor Author

That makes sense, if you send the PR I am happy to review 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants