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

Do not return nonexistent kinds in SyntaxFacts' methods #72264

Merged
merged 11 commits into from
Mar 22, 2024

Conversation

DoctorKrolic
Copy link
Contributor

@DoctorKrolic DoctorKrolic commented Feb 24, 2024

Fixes: #72300

@DoctorKrolic DoctorKrolic requested a review from a team as a code owner February 24, 2024 16:49
@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels Feb 24, 2024
@DoctorKrolic DoctorKrolic changed the title Do not return unexisting kind 8441 in SyntaxFacts' methods Do not return unexisting kinds in SyntaxFacts' methods Feb 26, 2024
@DoctorKrolic DoctorKrolic marked this pull request as draft February 26, 2024 12:23
@DoctorKrolic DoctorKrolic marked this pull request as ready for review February 26, 2024 17:53
@AlekseyTs
Copy link
Contributor

Do not return unexisting kinds in SyntaxFacts' methods

Could you please elaborate what the problem is and open an issue that describes a user-facing problem? Even though there is no member in the enum, the number is still reserved. And

@DoctorKrolic
Copy link
Contributor Author

Could you please elaborate what the problem is

I was working on a fix for #72258. I decided to populate all C# keywords' texts upfront, so I can later return them as completions. In order to achieve that I used SyntaxFacts.GetKeywordKinds() method and then saved keyword text by calling SyntaxFacts.GetText(kind) on each kind. When it came to verifying my work I noticed that there was 1 completion with empty text. A quick debug session showed that GetKeywordKinds has unexisting kind 8441 as part of returned collection of kinds. This led to this PR being opened. Then Youssef suggested adding guarding assert and I added such for all methods with similar integer looping logic. Failed CI then showed that SyntaxFacts.GetPunctuationKinds() also returns unexisting kinds and a lot of them. After fixing it I thought that corresponding SyntaxFacts.IsXXX checks should also not assume anything about unexisting kinds. SyntaxFacts.IsKeywordKind() already specifies all contextual keywords 1 by 1, so it didn't need fixing. SyntaxFacts.IsPunctuation() on the other hand did a range check, so I modified it to exclude unexisting kinds there. Now we are at this state.

open an issue that describes a user-facing problem

Even though there is no member in the enum, the number is still reserved

It is perfectly fine to reserve number ranges for different kinds of enum values. I would say, it is also fine to return unexisting kinds in an internal API, since this fact can then be shared as a common knowledge in the team, so additional checks can be made on caller side if necessary. However, this is public API and I can say with a very high level of certainty that consumers of public API by default assume that if API returns an enum value, this is an actual existing value of that enum. So I would classify this as a bug regardless of the user scenario it was discovered in (and I provided the way I personally discovered it)

@AlekseyTs
Copy link
Contributor

So I would classify this as a bug regardless of the user scenario it was discovered in (and I provided the way I personally discovered it)

I am afraid we still need an issue, especially as you classify the behavior as a bug.

@DoctorKrolic
Copy link
Contributor Author

I am afraid we still need an issue, especially as you classify the behavior as a bug.

Filled #72300 and #72301. I'll put this PR into a draft state until both issues are discussed and approved as actual bugs. Personally I feel very strongly about the first one being a bug and less strongly about the second one (but it is still not normal behavior IMO)

@DoctorKrolic DoctorKrolic marked this pull request as draft February 28, 2024 10:10
@DoctorKrolic DoctorKrolic force-pushed the avoid-unexisting-kind branch from 4ab304c to 2254bfb Compare March 12, 2024 17:16
@DoctorKrolic
Copy link
Contributor Author

@AlekseyTs #72300 has been classified as a bug. I've reverted other changes in this PR, so it only fixes that issue. This is now ready for review

@DoctorKrolic DoctorKrolic marked this pull request as ready for review March 12, 2024 17:19
@DoctorKrolic DoctorKrolic changed the title Do not return unexisting kinds in SyntaxFacts' methods Do not return nonexistent kinds in SyntaxFacts' methods Mar 12, 2024
@AlekseyTs
Copy link
Contributor

Done with review pass (commit 6)

@DoctorKrolic DoctorKrolic requested a review from AlekseyTs March 17, 2024 08:53
@AlekseyTs
Copy link
Contributor

Done with review pass (commit 8)

@DoctorKrolic DoctorKrolic requested a review from AlekseyTs March 18, 2024 13:08
@AlekseyTs
Copy link
Contributor

Done with review pass (commit 9)

@DoctorKrolic DoctorKrolic requested a review from AlekseyTs March 22, 2024 15:40
@AlekseyTs
Copy link
Contributor

Done with review pass (commit 10)

@@ -142,9 +145,10 @@ public static IEnumerable<SyntaxKind> GetPreprocessorKeywordKinds()
yield return SyntaxKind.TrueKeyword;
yield return SyntaxKind.FalseKeyword;
yield return SyntaxKind.DefaultKeyword;
yield return SyntaxKind.HiddenKeyword;

for (int i = (int)SyntaxKind.ElifKeyword; i <= (int)SyntaxKind.RestoreKeyword; i++)
Copy link
Contributor Author

@DoctorKrolic DoctorKrolic Mar 22, 2024

Choose a reason for hiding this comment

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

The [SyntaxKind.ElifKeyword - SyntaxKind.RestoreKeyword] range already contains SyntaxKind.HiddenKeyword, so I removed the duplicate. Found while working on tests

@DoctorKrolic DoctorKrolic requested a review from AlekseyTs March 22, 2024 18:08
Copy link
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

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

LGTM (commit 11), assuming CI is passing.

@AlekseyTs AlekseyTs requested a review from a team March 22, 2024 18:12
@AlekseyTs
Copy link
Contributor

@dotnet/roslyn-compiler For the second review.

@jcouv jcouv self-assigned this Mar 22, 2024
@DoctorKrolic DoctorKrolic requested a review from jcouv March 22, 2024 18:32
Copy link
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

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

LGTM Thanks (iteration 11)

@jcouv
Copy link
Member

jcouv commented Mar 22, 2024

/azp run

Copy link

Azure Pipelines successfully started running 2 pipeline(s).

@jcouv jcouv merged commit 07457ae into dotnet:main Mar 22, 2024
24 of 27 checks passed
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Mar 22, 2024
@jcouv
Copy link
Member

jcouv commented Mar 22, 2024

Merged/squashed. Thanks for the contribution!

@DoctorKrolic DoctorKrolic deleted the avoid-unexisting-kind branch March 23, 2024 05:22
@RikkiGibson RikkiGibson modified the milestones: Next, 17.10 P3 Mar 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
Development

Successfully merging this pull request may close these issues.

SyntaxFacts's GetXXXKinds methods can return nonexistent syntax kinds
5 participants