Skip to content

Maintain the same parse option when add symbol to destination#53001

Merged
Cosifne merged 7 commits intodotnet:release/dev16.11from
Cosifne:dev/shech/propertyGeneratorFix
May 19, 2021
Merged

Maintain the same parse option when add symbol to destination#53001
Cosifne merged 7 commits intodotnet:release/dev16.11from
Cosifne:dev/shech/propertyGeneratorFix

Conversation

@Cosifne
Copy link
Member

@Cosifne Cosifne commented Apr 28, 2021

Issue:
#51779

Reason:
When adding a symbol to a syntax node, the newly generated syntax node won't have a parent node, and therefore, it will use the default parse option. And later, we always think the default option as C# 9.

Fix:
After the destination node is generated, regenerate the syntax tree use the correct parse option. (Thanks Jason's help to point the right way to fix this)

@ghost ghost added the Area-IDE label Apr 28, 2021
@Cosifne Cosifne force-pushed the dev/shech/propertyGeneratorFix branch from c6164c4 to a16677f Compare April 29, 2021 06:33
@CyrusNajmabadi
Copy link
Contributor

Can you calrify how this fixes things? the destination syntax tree should have valid options for us to use. If it doesn't, i think we need to track back waht caused that.

@Cosifne
Copy link
Member Author

Cosifne commented Apr 29, 2021

Can you calrify how this fixes things? the destination syntax tree should have valid options for us to use. If it doesn't, i think we need to track back waht caused that.

@CyrusNajmabadi
Yeah, so the root reason for the bug is, if the parsing option is targeting C# 5, adding multiple member to the destination would cause problem at this line http://sourceroslyn.io/#Microsoft.CodeAnalysis.Workspaces/CodeGeneration/AbstractCodeGenerationService.cs,278
every time a new destination node is generated and returned in for loop, the parse option become C# 9. It causes the next generated syntax node doesn't perserve the C# 5 style.

I am testing this simple fix to see if this would cause any error. : ) And it does. So I am trying to another way to fix this

@CyrusNajmabadi
Copy link
Contributor

the parse option become C# 9.

This seems like teh bug :)

@Cosifne Cosifne changed the base branch from release/dev16.10 to release/dev16.11 May 5, 2021 01:25
{
cancellationToken.ThrowIfCancellationRequested();
currentDestination = UpdateDestination(availableIndices, options, currentDestination, member, cancellationToken);
currentDestination = UpdateDestination(availableIndices, options, currentDestination, member, destination.SyntaxTree.Options, cancellationToken);
Copy link
Member Author

Choose a reason for hiding this comment

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

When the symbol is passed to Property/Field/Method Generator, the generated syntax node doesn't have parent.
So its parse definition would be https://sourceroslyn.io/#Microsoft.CodeAnalysis.CSharp/CSharpParseOptions.cs,21

And later the default option is translated to the latest C# version https://sourceroslyn.io/#Microsoft.CodeAnalysis.CSharp/LanguageVersion.cs,426
Therefore when this loop is being called, its parsing option may change after the first iteration. (As this is the reason for this bug, C# 5 becomes C# 9 at this point)

The best way I feel here is to first generate all the syntax nodes for members using the same parse option, and then doing the insertion.

This would need to refactor a lot of code in the CodeGenerationService and the method/field/.. generator.
before I do this
tag @CyrusNajmabadi to see if this is the right way to fix this

Copy link
Contributor

Choose a reason for hiding this comment

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

The best way I feel here is to first generate all the syntax nodes for members using the same parse option, and then doing the insertion.

I'm not opposed to that. However, I feel like something is still wrong here:

And later the default option is translated to the latest C# version

There should be some way to avoid this. Maybe @jasonmalinowski knows? It seems patently weird that we fork nodes and trees, but end up changing the options here. Would prefer we avoid that, or force the options to be what we started with.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm fine with us exploring both options in parallel btw.

Copy link
Member

Choose a reason for hiding this comment

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

So the problem is a node created in isolation of a tree doesn't have any options. We create a tree on the fly when asked, but since there's no options it has no choice but to just use the default ones.

The alternative here would be in the path where we have a node and want the option to be remembered would be to explicitly call CSharpSyntaxTree.Create passing in the random node that we created with the option, and then grab the new red node root back from that. That means later calls to node.Tree.Options will have what you want.

@Cosifne Cosifne marked this pull request as ready for review May 17, 2021 17:57
@Cosifne Cosifne requested a review from a team as a code owner May 17, 2021 17:57
@Cosifne Cosifne changed the title Use CodeGenerationOption if possible Maintain the same parse option when add symbol to destination May 17, 2021
@Cosifne Cosifne force-pushed the dev/shech/propertyGeneratorFix branch from fbccba7 to 1f0ac0f Compare May 19, 2021 17:45
@Cosifne Cosifne enabled auto-merge May 19, 2021 17:52
@Cosifne Cosifne merged commit f4b3f5d into dotnet:release/dev16.11 May 19, 2021
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.

4 participants