-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Test/adjust keyword recommendations for Global Using directives #52059
Test/adjust keyword recommendations for Global Using directives #52059
Conversation
@CyrusNajmabadi, @dotnet/roslyn-compiler Please review. |
{ | ||
await VerifyKeywordAsync( | ||
@"using Goo; | ||
$$"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this technically isn't legal right? global usings need to come before normal usings? Or do we allow them to come after?
Note: even if this is not legal, i'm fine with the keyword recommender offering this. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this technically isn't legal right? global usings need to come before normal usings? Or do we allow them to come after?
Note: even if this is not legal, i'm fine with the keyword recommender offering this.
You are correct. It is not legal, but I think it is better to offer it and report an error, than to not offer it.
In reply to: 599780626 [](ancestors = 599780626)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but I think it is better to offer it and report an error, than to not offer it.
Agreed. I just wanted to make sure my mental model was correct. In the impl it would be good to have a comment stating that in the place where we make the decisino just to make the intent clear. Up to you. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the impl it would be good to have a comment stating that in the place where we make the decisino just to make the intent clear. Up to you.
There isn't really a logict to specifically allow that. We simply do not make any effort to disallow.
In reply to: 599801190 [](ancestors = 599801190)
await VerifyAbsenceAsync( | ||
@"global using Goo; | ||
global $$ | ||
using Bar;"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add a test about adding it before a namespace, class, top level statement, and global/normal attributes? #Resolved
@@ -36,6 +36,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context | |||
return | |||
context.IsStatementContext || | |||
context.IsGlobalStatementContext || | |||
UsingKeywordRecommender.IsUsingDirectiveContext(context, forGlobalKeyword: true, cancellationToken) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't love this in that it seems to go against the general 'context' pattern we have. but i'm not opposed to this, and i'm willing to make the change to unify this with the existing pattern if you're ok with that @AlekseyTs #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and i'm willing to make the change to unify this with the existing pattern if you're ok with that
Are you talking about unifing this in a follow-up PR, or in contect of this PR. I am not sure it is clear to me what you are offering.
In reply to: 599782529 [](ancestors = 599782529)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, my preference is that we have a new boolean property on the context object (Called something like IsUsingDirectiveContext and IsGlobalUsingContext). And then this recommender would just check that.
I'm also saying that i'm not expecting that in this PR. I'm also saying, if you'd rather i make that change, i'm happy to do that as well in a followup PR. I don't expect you to have to make that change. Thanks! #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, my preference is that we have a new boolean property on the context object (Called something like IsUsingDirectiveContext and IsGlobalUsingContext). And then this recommender would just check that.
I'm also saying that i'm not expecting that in this PR. I'm also saying, if you'd rather i make that change, i'm happy to do that as well in a followup PR. I don't expect you to have to make that change. Thanks!
Thanks for clarifying. I'll let you follow up on this, especially that IsUsingDirectiveContext isn't a property on the context today and I am not sure if it is worth making it a property and precomputing its value (it looks like some properties on the context are precomputed) for scenarios when it is not even needed.
In reply to: 599802941 [](ancestors = 599802941)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good to me #Resolved
} | ||
|
||
return true; | ||
return isValidContextAtTheRoot(context, originalToken, cancellationToken); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IDE naming rule for local functions is to PascalCAse them :) we think of them more as methods than as locals. #Resolved
(previousToken.Parent.IsKind(SyntaxKind.ExternAliasDirective) || | ||
previousToken.Parent.IsKind(SyntaxKind.UsingDirective))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(previousToken.Parent.IsKind(SyntaxKind.ExternAliasDirective) || | |
previousToken.Parent.IsKind(SyntaxKind.UsingDirective))) | |
previousToken.Parent.IsKind(SyntaxKind.ExternAliasDirective, SyntaxKind.UsingDirective)) | |
``` #Resolved |
{ | ||
if (token.Kind() == SyntaxKind.GlobalKeyword) | ||
{ | ||
if (!token.Parent.IsKind(SyntaxKind.UsingDirective) || token.TrailingTrivia.Any(SyntaxKind.EndOfLineTrivia)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interesting. can you comment what teh EOL case is for? #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and, by 'comment' i mean: leave a comment in the code. not in the PR. thanks! #Resolved
@@ -13,11 +13,12 @@ namespace Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery | |||
{ | |||
internal static partial class SyntaxTokenExtensions | |||
{ | |||
public static bool IsUsingOrExternKeyword(this SyntaxToken token) | |||
public static bool IsStartOfUsingOrExternDirective(this SyntaxToken token) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hrmm.. this isn't quite accurate now. prior it was really just askign about the keywords. now it strongly implies that it's at the start of the directive. but that's not really true for the checks below anymore. for exampple using var x
or public extern void Foo()
would both return true here, but wouldn't really be the start of a using/extern directive. Consider keeping the method the same, and possibly adding the global check to the caller? #Resolved
Love the tests. A couple of nits around the impl. I'm happy to take this up if you'd prefer that. Or, if you're comfortable just making teh changes, that's great too. Thanks! #Resolved |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Compiler changes LGTM Thanks (iteration 3)
@CyrusNajmabadi I think I addressed feedback. |
@dotnet/roslyn-compiler Please review need a second sign-off for small changes in compiler. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Compiler changes LGTM.
else if (token.Kind() == SyntaxKind.IdentifierToken && SyntaxFacts.GetContextualKeywordKind((string)token.Value!) == SyntaxKind.GlobalKeyword) | ||
{ | ||
return true; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so there's a slight corner here that you could fixup if you wanted. it looks like with this that if you have:
extern alias Foo;
tehn we won't offer here:
$$
extern alias Foo;
but if you have:
extern alias Foo;
$$
extern alias Bar;
taht we will offer.
this is likely so minor as to be irrelevant though :) #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so there's a slight corner here that you could fixup if you wanted. it looks like with this that if you have:
I'd say that this is a preexisting condition and the current behavior around offering using
keyword (when global
) isn't present. I'll open an issue to decide if we want that addressed.
In reply to: 600021445 [](ancestors = 600021445)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IDE side lgtm. thanks for all the tests
Relates to #51307 (test plan for global usings)