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

F1 help for #if and #else refers to preprocessor symbols, not if_CSharpKeyword and else_CSharpkeyword #69192

Merged
merged 5 commits into from
Aug 1, 2023

Conversation

BillWagner
Copy link
Member

@BillWagner BillWagner commented Jul 24, 2023

The F1 service should produce #if instead of if_CSharpKeyword when the cursor is on the #if symbol.

Fixes dotnet/docs#35715

Add tests for the F1 service on #if and related tokens. Then, when checking for keywords, make sure that if and else have the proper statement token as the parent token. Otherwise, that text is part of the preprocessor token.

The F1 service should produce `#if` instead of `if_CSharpKeyword` when
the cursor is on the `#if` symbol.

Add other tasks for the other preprocessor symbols related to
conditional compilation. The `#if` and `#else` fail, because the model
finds child nodes for `if` and `else`, respectively. The tests for
`#elif` and `#endif` pass, because the model does not find child nodes
for those tokens.
@dotnet-issue-labeler dotnet-issue-labeler bot added Area-IDE untriaged Issues and PRs which have not yet been triaged by a lead labels Jul 24, 2023
@ghost ghost added the Community The pull request was submitted by a contributor who is not a Microsoft employee. label Jul 24, 2023
Because the `#if` and `#else` preprocessor tokens contain the text for keywords (`if` and `else`), the `TryGetTextForKeyword` would lock to those keywords before the `TryGetTextForPreProcessor` looked for the preprocessor token. By switching the order of those two tests, the longer preprocessor tokens are found first.
The "if" and "else" nodes may appear as "if" / "else" or "#if" / "#else".

If the parent isn't the if statement or else clause, don't treat them as keywords. Then, the later processing will find them as preprocessor tokens and correctly route the request.
@BillWagner BillWagner marked this pull request as ready for review July 31, 2023 22:25
@BillWagner BillWagner requested a review from a team as a code owner July 31, 2023 22:25
@BillWagner
Copy link
Member Author

ping @CyrusNajmabadi

@BillWagner
Copy link
Member Author

Commit notes for reviewers:

  1. First commit: Add other tests for the other preprocessor symbols related to conditional compilation. The #if and #else fail, because the model finds child nodes for if and else, respectively. The tests for #elif and #endif pass, because the model does not find child nodes for those tokens.
  2. Second commit: Make failing tests pass. Because the #if and #else preprocessor tokens contain the text for keywords (if and else), the TryGetTextForKeyword would lock to those keywords before the TryGetTextForPreProcessor looked for the preprocessor token. By switching the order of those two tests, the longer preprocessor tokens are found first.
  3. Third commit:: Revert second commit, because that broke several tests for "default" text that was being interpreted as "#default". Instead, check the parent of the node when "if" and "else" are found. If the parent isn't the IfStatement or ElseClause, respectively, don't consider the token a keyword. The later test for a preprocessor token will find the correct node.

Copy link
Member

@genlu genlu left a comment

Choose a reason for hiding this comment

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

:shipit:

@CyrusNajmabadi
Copy link
Member

looking.

@CyrusNajmabadi
Copy link
Member

Let me take a stab at this.

TryGetTextForPreProcessor(token, out text) ||
TryGetTextForKeyword(token, out text) ||
Copy link
Member

Choose a reason for hiding this comment

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

have pp checks come first so we defer to the pp interepretation if inside a directive.


if (token.IsKind(SyntaxKind.EndOfDirectiveToken) && token.GetAncestor<RegionDirectiveTriviaSyntax>() != null)
Copy link
Member

Choose a reason for hiding this comment

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

unified the behavior here so it works for any directive, not just regions.

{
text = Keyword("defaultline");
return true;
}
Copy link
Member

Choose a reason for hiding this comment

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

moved from the keyword handling case to the directive handling case.

@CyrusNajmabadi CyrusNajmabadi merged commit b402c4d into dotnet:main Aug 1, 2023
24 checks passed
@ghost ghost added this to the Next milestone Aug 1, 2023
@BillWagner BillWagner deleted the f1-if-pragma branch August 2, 2023 13:29
@dibarbet dibarbet modified the milestones: Next, 17.8 P2 Aug 28, 2023
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. 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.

F1 on '#if' takes me here to 'if'. It may be helpful here to have a see-also '#if'.
4 participants