Skip to content

Adding missing completion after 'ref'#25570

Merged
DustinCampbell merged 18 commits intodotnet:masterfrom
Neme12:refCompletion
Apr 5, 2018
Merged

Adding missing completion after 'ref'#25570
DustinCampbell merged 18 commits intodotnet:masterfrom
Neme12:refCompletion

Conversation

@Neme12
Copy link
Copy Markdown
Contributor

@Neme12 Neme12 commented Mar 18, 2018

Customer scenario

Type 'ref' and expect completion for 'readonly'
Type 'ref' or 'ref readonly' and expect symbol & keyword completion
(examples in the issue)

Bugs this fixes

fixes #25569

Workarounds, if any

Type whatever you need to type manually.

Risk

not sure

Performance impact

I only added syntax checks, so... low?

Is this a regression from a previous update?

No.

Root cause analysis

New language feature without full completion.

How was the bug found?

I found it by exploration.

@Neme12 Neme12 requested a review from a team as a code owner March 18, 2018 15:21
// the syntax tree is completely broken and there is no lambda expression at all here.
// 'ref' starts a new local declaration and therefore we do offer 'readonly'.
// Fixing that would have to involve either changing the parser or doing some really nasty hacks.
// Delegate lambda = (ref $$ int p) => p;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

not sure what to do here

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

file bug.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't think this is a bug

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah, I agree with @CyrusNajmabadi. File a bug. We can do a better job with error recovery in the parser here.

@jcouv
Copy link
Copy Markdown
Member

jcouv commented Mar 18, 2018

Thanks! Tagging @VSadov and @OmarTawfik as FYI

@jcouv jcouv added Area-IDE Community The pull request was submitted by a contributor who is not a Microsoft employee. labels Mar 18, 2018
@jcouv jcouv added this to the 15.8 milestone Mar 18, 2018
@Neme12 Neme12 changed the title Adding missng completion after 'ref' Adding missing completion after 'ref' Mar 18, 2018
// cases:
// const var
// ref var
// ref readonly var
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

these comment should move down to the new block you added. right?

Copy link
Copy Markdown
Contributor Author

@Neme12 Neme12 Mar 18, 2018

Choose a reason for hiding this comment

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

actually all cases are on the top of the method here, see the rest of the comment - it's all below code i added

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

or do you want me to move each comment to the relevant place where it's handled?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yes.

Copy link
Copy Markdown
Contributor Author

@Neme12 Neme12 Mar 18, 2018

Choose a reason for hiding this comment

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

i'm not sure if i should make code style changes like that unrelated to what i'm doing and mess with half of this method by moving comments, given that this PR is already large enough

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

that's fair. do as you wish.

}

if (token.IsKind(SyntaxKind.RefKeyword, SyntaxKind.ReadOnlyKeyword) &&
token.Parent.IsKind(SyntaxKind.RefType) &&
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

didn't you jsut add a new helper that does this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

no I didn't... and even if I did, this is a special case because this is used for var, which can't be offer in other places after a ref type (eg in a method return type)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So this is not just the same as "IsAfterRefTypeContext"?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

no it's not:

class C
{
    ref $$
}

here you're in a ref type but not in a local declaration and can't use var

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this method is called 'IsLocalVariableDeclarationContext'

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor

Tagging @dotnet/roslyn-ide @jinujoe . it looks large, but the majority is just a super-exhaustive test suite (yaay). Actual code change is quite minor and easy to review.

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Mar 18, 2018

I should note: all the "type" "keywords" behave the same and have the same tests except for

  1. var, as expected it's only offered after a ref type in a local declaration
  2. dynamic - it's offered after a ref type but not after a ref expression (I can't think of any case where that would be legal - correct me if I'm wrong)

}
}
";
await VerifyItemExistsAsync(markup, "String");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why do we offer "String" here?

Copy link
Copy Markdown
Contributor Author

@Neme12 Neme12 Mar 19, 2018

Choose a reason for hiding this comment

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

@jcouv String.Empty.MyRefReturningExtensionMethod()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah, thanks

context.IsPrimaryFunctionExpressionContext ||
context.IsCrefContext ||
syntaxTree.IsAfterKeyword(position, SyntaxKind.ConstKeyword, cancellationToken) ||
syntaxTree.IsAfterKeyword(position, SyntaxKind.RefKeyword, cancellationToken) ||
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm surprised this doesn't fall under a more abstract category, like "IsTypeContext" or "IsPossibleTypeContext" (those are made-up, I'm not sure whether such methods exist). If there is not one, consider factoring one out, or filing an issue to do so.
Note: this would avoid duplicating the fix to multiple recommenders.

@dotnet/roslyn-ide for advice. Is there already a check that would be suitable for this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One more thought on this. Is there a reason that all the recommenders for intrinsic types (bool, byte, string, object, etc) don't just share code?


In reply to: 175509814 [](ancestors = 175509814)

Copy link
Copy Markdown
Contributor Author

@Neme12 Neme12 Mar 19, 2018

Choose a reason for hiding this comment

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

@jcouv I was really surprised by this too and asked @CyrusNajmabadi who said this is very much by design. I would still like to do some cleanup here and reduce the duplication to some degree but I'm not going to do that as part of this PR. Is that OK?

Copy link
Copy Markdown
Contributor Author

@Neme12 Neme12 Mar 19, 2018

Choose a reason for hiding this comment

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

@CyrusNajmabadi mentioned to me that for starters there are some cases (enum base list, stackalloc) where only some of those keywords are allowed, that's why they can't share everything and often do require special treatment. That said, I still think the duplication could be reduced significantly, but I'm treating this PR as a bugfix rather than code quality improvement/refactoring. It would not be as trivial as it seems.
(but I agree with you 100%, I don't like the code the way it is)

Copy link
Copy Markdown
Contributor Author

@Neme12 Neme12 Mar 19, 2018

Choose a reason for hiding this comment

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

It woud require refactoring some of the existing helpers to be more fine-grained to support this sort of distinction. Yes, there is a helper called IsTypeContext but it is more general and offered in more places than these keywords, not less - so it's not as easy as using that helper and then adding more checks with ||.

Copy link
Copy Markdown
Contributor Author

@Neme12 Neme12 Mar 19, 2018

Choose a reason for hiding this comment

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

But @CyrusNajmabadi has a lot more to say about this than I do. I talked to him about this and and he was clearly opposed to the idea of generalizing these too much. I think I understand his concerns and hope we can find a good tradeoff here. But that would be for another PR.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm surprised this doesn't fall under a more abstract category, like "IsTypeContext" or "IsPossibleTypeContext" (those are made-up, I'm not sure whether such methods exist). If there is not one, consider factoring one out, or filing an issue to do so.

We can consider these sorts of things. However, as i mentioned to @Neme12 it gets a little subtle due to different types being legal in different contexts.

One more thought on this. Is there a reason that all the recommenders for intrinsic types (bool, byte, string, object, etc) don't just share code?

Yes. Not all of them are allowed in the same contexts. For example, after stackalloc, you can have types, but not all types.

Similarly, you can have integral types (but not floating point types) in an enum-base-list.

--

Now, as i mentioned to @Neme12 we could certainly extract out some contexts that were well defined, and would make sense for large sets of these providers. For example: IsIntegralTypeContext (for non-floating point numeric types).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the clarification. I certainly agree it doesn't need to be solved in this PR.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@Neme12 has shown a great interest in improving things here based on supporting all our existing goals, while also massively reducing duplication. I'm really excited to see what we can do here!

Copy link
Copy Markdown
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

@jcouv
Copy link
Copy Markdown
Member

jcouv commented Mar 19, 2018

@dotnet/roslyn-ide for review of this community PR. Thanks

@jcouv
Copy link
Copy Markdown
Member

jcouv commented Mar 21, 2018

@dotnet/roslyn-ide Please review this community PR and merge. Thanks

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Mar 21, 2018

retest windows_release_unit32_prtest please

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Mar 21, 2018

@dotnet-bot retest windows_debug_vs-integration_prtest please

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Mar 21, 2018

the test shows 404 😕

HTTP ERROR 404
Problem accessing /job/dotnet_roslyn/job/master/job/windows_debug_vs-integration_prtest/10936/. Reason:

    Not Found
Powered by Jetty:// 9.4.z-SNAPSHOT

@jcouv
Copy link
Copy Markdown
Member

jcouv commented Mar 22, 2018

@dotnet/roslyn-ide Please review this community PR and merge. Thanks

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Mar 29, 2018

retest windows_debug_vs-integration_prtest please

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Mar 29, 2018

retest windows_release_vs-integration_prtest please

@jcouv
Copy link
Copy Markdown
Member

jcouv commented Mar 30, 2018

@dotnet/roslyn-ide Cyrus and I reviewed this community PR. Can you complete the review? It's been a week without response. Thanks

Copy link
Copy Markdown
Member

@DustinCampbell DustinCampbell left a comment

Choose a reason for hiding this comment

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

This is great work @Neme12! Thank you for all of the added tests.

@DustinCampbell
Copy link
Copy Markdown
Member

@dotnet-bot retest this please

1 similar comment
@jcouv
Copy link
Copy Markdown
Member

jcouv commented Apr 5, 2018

@dotnet-bot retest this please

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Apr 5, 2018

retest windows_release_unit64_prtest please

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Apr 5, 2018

retest windows_debug_unit32_prtest please

@jcouv
Copy link
Copy Markdown
Member

jcouv commented Apr 5, 2018

Whoever ends up merging this PR. Beware that it contains some merge commits (ie. do not squash this merge).

@DustinCampbell
Copy link
Copy Markdown
Member

This is another great contribution @Neme12 -- thanks!

@DustinCampbell DustinCampbell merged commit d27cfde into dotnet:master Apr 5, 2018
@Neme12 Neme12 deleted the refCompletion branch April 6, 2018 06:51
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

Development

Successfully merging this pull request may close these issues.

Missing completion after 'ref'

5 participants