Skip to content

Fix SyntaxGenerator.WithModifiers to recognize ClassStatement, not only ClassBlock#53628

Merged
CyrusNajmabadi merged 7 commits intodotnet:mainfrom
Youssef1313:syntax-gen-vb
Jun 21, 2021
Merged

Fix SyntaxGenerator.WithModifiers to recognize ClassStatement, not only ClassBlock#53628
CyrusNajmabadi merged 7 commits intodotnet:mainfrom
Youssef1313:syntax-gen-vb

Conversation

@Youssef1313
Copy link
Member

@Youssef1313 Youssef1313 commented May 23, 2021

Fixes #53627
Fixes #50003

This has a breaking change for public API. If it is not desired, let me know (Outdated now. Went another route per review)

@Youssef1313 Youssef1313 requested a review from a team as a code owner May 23, 2021 02:48
@ghost ghost added the Area-IDE label May 23, 2021
@CyrusNajmabadi
Copy link
Contributor

The original logic is intended here.

@Youssef1313
Copy link
Member Author

Thanks @CyrusNajmabadi, will go to another route.

@Youssef1313 Youssef1313 changed the title Fix syntax generator to recognize VB's statements, not only blocks Fix SyntaxGenerator.WithModifiers to recognize ClassStatement, not only ClassBlock May 23, 2021
@Youssef1313 Youssef1313 requested review from CyrusNajmabadi and removed request for a team May 23, 2021 15:55
End Class",
"
Public MustOverride Class Foo
Public MustInherit Class Foo
Copy link
Contributor

Choose a reason for hiding this comment

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

given this example, i guess my surprise is that we are passing in hte class-statement, and not hte class-block for this feature.

Copy link
Member Author

Choose a reason for hiding this comment

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

@CyrusNajmabadi, yep, it passes the class statement.

Copy link
Contributor

Choose a reason for hiding this comment

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

i guess my fix would be at that level :) There is also an ISymbolDeclarationService that helps ensure that we work with the right node (if this is a feature that uses symbols).

Copy link
Member Author

Choose a reason for hiding this comment

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

@CyrusNajmabadi The fix is mainly for the public SyntaxGenerator.WithModifiers API

Copy link
Contributor

Choose a reason for hiding this comment

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

i guess my point is this: i think it's hte feature working improperly. i would update the feature. if we update the generator, we need to update it to support all statements for blocks, and it was intentional that we were not conflating these at that level.

Copy link
Member Author

Choose a reason for hiding this comment

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

@CyrusNajmabadi For the purpose of WithModifiers, supporting other statements won't have effect. For SyntaxGenerator in general, I'm not sure what other parts are affected by but supporting blocks only and not statements?

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 not sure i get your question. it feels very strange to just special case class statements here (what about structs/interfaces/modules)?

Copy link
Member Author

@Youssef1313 Youssef1313 May 24, 2021

Choose a reason for hiding this comment

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

@CyrusNajmabadi In this specific code path. They have no effect. The declaration kind is passed to GetModifierList:

Private Shared Function GetModifierList(accessibility As Accessibility, modifiers As DeclarationModifiers, kind As DeclarationKind, Optional isDefault As Boolean = False) As SyntaxTokenList

And it doesn't perform any checks against interfaces, structures, etc.

Dim newTokens = GetModifierList(acc, modifiers And GetAllowedModifiers(declaration.Kind), GetDeclarationKind(declaration), isDefault)
If currentMods <> modifiers Then
Dim declarationKind = GetDeclarationKind(declaration)
If declarationKind = DeclarationKind.None AndAlso declaration.IsKind(SyntaxKind.ClassStatement) Then
Copy link
Contributor

Choose a reason for hiding this comment

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

i don't get it. this is directly making a change purely for classes. i dont' see why we wouldn't need the same for structs/interfaces/modules here.

And, like i said before, i thinik the bug is that hte caller is passing ina class statement, it should pass in a classblock.

Copy link
Member Author

Choose a reason for hiding this comment

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

i thinik the bug is that hte caller is passing ina class statement, it should pass in a classblock.

I believe API consumers won't expect this at all.


i don't get it. this is directly making a change purely for classes. i dont' see why we wouldn't need the same for structs/interfaces/modules here.

Because it literally doesn't have any effect. If you look at the following method:

Private Shared Function GetModifierList(accessibility As Accessibility, modifiers As DeclarationModifiers, kind As DeclarationKind, Optional isDefault As Boolean = False) As SyntaxTokenList

Any type declaration other than a class will be treated the same. I could handle all other statements, but it doesn't have any functional/behavioral change.

Copy link
Member Author

Choose a reason for hiding this comment

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

i thinik the bug is that hte caller is passing ina class statement, it should pass in a classblock.

I believe API consumers won't expect this at all.


i don't get it. this is directly making a change purely for classes. i dont' see why we wouldn't need the same for structs/interfaces/modules here.

Because it literally doesn't have any effect. If you look at the following method:

Private Shared Function GetModifierList(accessibility As Accessibility, modifiers As DeclarationModifiers, kind As DeclarationKind, Optional isDefault As Boolean = False) As SyntaxTokenList

Any type declaration other than a class will be treated the same. I could handle all other statements, but it doesn't have any functional/behavioral change.

Copy link
Member Author

Choose a reason for hiding this comment

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

To put it another way, there is no way to write a unit test for interface/structure that can fail now and be fixed by handling statements in this code path. WithModifiers already works correctly for the other declarations.

Copy link
Contributor

Choose a reason for hiding this comment

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

i don't really get it.

I believe API consumers won't expect this at all.

I don't have an issue with htat. It was an explicit decision that we do not try to blur the lines between the statements and blocks. The block corresponds to the decl, and the api here intends to operate on the decls.

Copy link
Contributor

Choose a reason for hiding this comment

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

this is my approach: #50003

Copy link
Member Author

Choose a reason for hiding this comment

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

@CyrusNajmabadi Well, Part of the disconnect is whether WithModifiers should work with statements, or only blocks. It currently works with statements very well, except for the class case (more specifically sealing the class). Anything other than sealing a class works correctly using either a statement or a block. This is one of the reasons I think WithModifiers should get modified to work with class statement, even if the original design didn't intend that.

Otherwise, a clear doc comment should make this clear. (and in this case, you can close the PR and #53627)

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi May 25, 2021

Choose a reason for hiding this comment

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

i would then update GetModifierList to put the special logic there. specifically, it should not pass in a declaration kind in isolation. it can pass in both. or just pass in hte node, and compute the declaration kind there, but use it with the node to figure out what to do.

Copy link
Member Author

Choose a reason for hiding this comment

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

@CyrusNajmabadi The suggested approach is a lot easier to follow and to reason about. Only problem I found is that most callers don't have a relevant SyntaxNode to pass. So I passed Nothing for these cases.

@jinujoseph jinujoseph added the Community The pull request was submitted by a contributor who is not a Microsoft employee. label May 25, 2021
@CyrusNajmabadi CyrusNajmabadi merged commit 36c1a37 into dotnet:main Jun 21, 2021
@ghost ghost added this to the Next milestone Jun 21, 2021
@CyrusNajmabadi
Copy link
Contributor

thanks!

@Youssef1313 Youssef1313 deleted the syntax-gen-vb branch June 21, 2021 19:20
@RikkiGibson RikkiGibson modified the milestones: Next, 17.0.P2 Jun 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-IDE Community The pull request was submitted by a contributor who is not a Microsoft employee.

Projects

None yet

4 participants