Skip to content

Escape keywords in object initializer completion#26740

Merged
ivanbasov merged 3 commits intodotnet:masterfrom
mikkelbu:objectcreationinitializer-escape-keywords
May 15, 2018
Merged

Escape keywords in object initializer completion#26740
ivanbasov merged 3 commits intodotnet:masterfrom
mikkelbu:objectcreationinitializer-escape-keywords

Conversation

@mikkelbu
Copy link
Copy Markdown
Contributor

@mikkelbu mikkelbu commented May 9, 2018

Fixes #26560

Ask Mode template not completed

Customer scenario

What does the customer do to get into this situation, and why do we think this
is common enough to address for this release. (Granted, sometimes this will be
obvious "Open project, VS crashes" but in general, I need to understand how
common a scenario is)

Bugs this fixes

(either VSO or GitHub links)

Workarounds, if any

Also, why we think they are insufficient for RC vs. RC2, RC3, or RTW

Risk

This is generally a measure our how central the affected code is to adjacent
scenarios and thus how likely your fix is to destabilize a broader area of code

Performance impact

(with a brief justification for that assessment (e.g. "Low perf impact because no extra allocations/no complexity changes" vs. "Low")

Is this a regression from a previous update?

Root cause analysis

How did we miss it? What tests are we adding to guard against it in the future?

How was the bug found?

(E.g. customer reported it vs. ad hoc testing)

Test documentation updated?

If this is a new non-compiler feature or a significant improvement to an existing feature, update https://github.com/dotnet/roslyn/wiki/Manual-Testing once you know which release it is targeting.

@mikkelbu mikkelbu requested a review from a team as a code owner May 9, 2018 18:55
@jinujoseph jinujoseph added Area-IDE Community The pull request was submitted by a contributor who is not a Microsoft employee. labels May 9, 2018
@jinujoseph
Copy link
Copy Markdown
Contributor

cc @jcouv

@jcouv jcouv self-assigned this May 9, 2018
{
context.AddItem(SymbolCompletionItem.CreateWithSymbolId(
displayText: uninitializedMember.Name,
displayText: uninitializedMember.ToNameDisplayString(),
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.

Since this code is shared for C# and VB, please also add a corresponding VB test. Thanks

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.

Needs a VB test, but otherwise looks good (iteration 1).

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor

Note: test failures look real.

If the member was a VB property with parameter(s) then
the completion would not be correct as `ToNameDisplayString()`
also includes the parameter(s). Hence, we only use
`ToNameDisplayString()`, if the member does not have parameters,
otherwise we keep the old behaviour.
@mikkelbu
Copy link
Copy Markdown
Contributor Author

mikkelbu commented May 9, 2018

I've pushed a test for VB and also corrected the logic. The problem was that for VB properties with parameters, the parameters would also be visible in the completion which did not make sense. So now we only use ToNameDisplayString(), if the member does not have any parameters, otherwise return to the old behaviour.

Illustration of the problem (highlighted by the two VB tests)
image


foreach (var uninitializedMember in uninitializedMembers)
{
var displayText = uninitializedMember.GetParameters().Length == 0 ? uninitializedMember.ToNameDisplayString() : uninitializedMember.Name;
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 don't think we want ToNameDisplayString at all.
Something is causing the insertion codepath to not go through CompletionUtilities.GetInsertionText (which would properly escape the string as necessary).

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.

The problem here seems to be that AbstractObjectINitializerCompletionProvider does not do the same things as AbstractSymbolCompletionProvider where it asks what the appropriate 'insertion' text should be.

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.

@CyrusNajmabadi I didn't fully understand your comment, but wanted to mention that in the completion for patterns (which had the same problem with escaping keywords), I used untestedMember.Name.EscapeIdentifier(). Would that be appropriate here as well?

See https://github.com/dotnet/roslyn/pull/26553/files#diff-71f1153caf63996a37515baedd143adbR53

Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi May 9, 2018

Choose a reason for hiding this comment

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

looking at this code overall... yup, i think that would be sufficient!


foreach (var uninitializedMember in uninitializedMembers)
{
var displayText = uninitializedMember.GetParameters().Length == 0 ? uninitializedMember.ToNameDisplayString() : uninitializedMember.Name;
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 not sure that checking the number of parameters is the correct way to filter out such members. It feels like we should look at the kind of member (field or properties are good for this completion, but methods are not).

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.

Agreed. This is patching things up at the wrong level. We have a mechanism to do this already in normal symbol completion. But unfortunately, we're not doing the same thing here. The right fix is to adopt that strategy. @mikkelbu I can provide more information if my explanation so far wasn't clear.

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.

@CyrusNajmabadi I think I need some more information. Originally when I looked into this issue I was also by AbstractSymbolCompletionProvider and I looked at CompletionUtilities.GetDisplayAndInsertionText, but I failed to discover that CompletionUtilities exists both as a C# and a VB class, so I took another approach.

Are you suggesting that I make a similar abstract method in AbstractObjectINitializerCompletionProvider and then use CompletionUtilities.GetDisplayAndInsertionText in the derived classes in C# and VB? And if so, should I also have something similar to the special handling in ObjectCreationCompletionProvider.GetDisplayAndInsertionText(...) and AbstractObjectCreationCompletionProvider.GetDisplayAndInsertionText(...).

Ps. GetDisplayAndInsertionText is using EscapeIdentifier to create the insertion text.

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 was my original suggestion for the overall 'best' approach here.

However, i think julien's suggestions is just as reasonable and far easier to accomplish. So i would just go with that.

Cheers!

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 May 10, 2018

@dotnet/roslyn-ide please review this community contribution. Thanks

@jinujoseph jinujoseph added this to the 15.8 milestone May 10, 2018
Copy link
Copy Markdown
Contributor

@ivanbasov ivanbasov left a comment

Choose a reason for hiding this comment

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

:shipit:


<WorkItem(26560, "https://github.com/dotnet/roslyn/issues/26560")>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TestKeywordsEscaped() As Task
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.

nit: it would be nice if this had the same name as the c# test (so it's easier to find both)

@ivanbasov
Copy link
Copy Markdown
Contributor

Thank you very much for your contribution, @mikkelbu, and for your help with review, @CyrusNajmabadi!

@ivanbasov ivanbasov closed this May 15, 2018
@ivanbasov ivanbasov reopened this May 15, 2018
@ivanbasov
Copy link
Copy Markdown
Contributor

sorry! closed it before merged. will have to wait for tests to complete again. will merge just after that.

@ivanbasov ivanbasov merged commit 8f4011d into dotnet:master May 15, 2018
@mikkelbu mikkelbu deleted the objectcreationinitializer-escape-keywords branch May 15, 2018 21:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Approved to merge 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.

ObjectCreationInitializer completion doesn't escape keywords

6 participants