Skip to content

Inline Hints: Added double click on hint to insert text#55737

Merged
akhera99 merged 29 commits intodotnet:mainfrom
akhera99:inline_hints_double_click
Jan 7, 2022
Merged

Inline Hints: Added double click on hint to insert text#55737
akhera99 merged 29 commits intodotnet:mainfrom
akhera99:inline_hints_double_click

Conversation

@akhera99
Copy link
Copy Markdown
Member

@akhera99 akhera99 commented Aug 19, 2021

Fixes: #55519

Added functionality in for parameter and type hints to be double-clicked and inserted into the text. Type hints replace var

@ghost ghost added the Area-IDE label Aug 19, 2021
@akhera99
Copy link
Copy Markdown
Member Author

akhera99 commented Aug 19, 2021

Edited behavior:

ConsoleApp7.-.Microsoft.Visual.Studio.Int.Preview.2021-08-20.15-30-56.mp4

@akhera99 akhera99 marked this pull request as ready for review August 19, 2021 23:04
@akhera99 akhera99 requested a review from a team as a code owner August 19, 2021 23:04
@akhera99 akhera99 requested a review from a team August 19, 2021 23:04
Copy link
Copy Markdown
Member

@JoeRobich JoeRobich left a comment

Choose a reason for hiding this comment

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

Looks good. I am excited to try this out

@akhera99 akhera99 changed the base branch from main to release/dev17.1-preview1 August 19, 2021 23:12
@akhera99 akhera99 requested review from a team as code owners August 19, 2021 23:12
@akhera99 akhera99 changed the base branch from release/dev17.1-preview1 to main August 19, 2021 23:13
@akhera99 akhera99 removed request for a team August 19, 2021 23:13
@CyrusNajmabadi
Copy link
Copy Markdown
Contributor

Added an option in C#/VB for parameter hints to be double-clicked and inserted into the text.

do we need an option for this? why not always support this? what's the use case for a user double-clicking on the hint and not inserting it?


result.Add(new InlineHint(
new TextSpan(position, 0),
ImmutableArray.Create(new TaggedText(TextTags.Text, parameter.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.

isn't the replacement text exactly the same as this string here? why not just compute it here and just add to the hint?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

done

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.

confused. you still generate parameter.Name + ": " here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

right, for C# and VB we generated "parameter:" for the hint itself, which I thought should remain the same. It only matters to generate the parameter:= for VB when you double click and replace the hint, which is why I added the "inlineHintText" var on line 94.

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.

interesting. it's arguable that the VB hint is wrong and should be foo:= to indicate the actual VB implied text... can you try that out and show me what it looks like? if it's not hideous, we could mvoe to that. If it's awful, then your solution is a good workaround.

=> _getDescriptionAsync?.Invoke(document, cancellationToken) ?? SpecializedTasks.EmptyImmutableArray<TaggedText>();

public string? GetReplacementText()
=> _getReplacementText?.Invoke() ?? null;
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.

why do we need an indirection here? it should be practically free to just store the TextChange struct.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

At that point, why would you need the TextChange struct as well?

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.

to know what text change to make :)

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.

isn't it easier to use the ITextBuffer.Replace instead of worrying about TextChange etc? We already have the IWpfTextView stored so calling Replace on the underlying buffer is trivial

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.

hints are data, and should work cross process. we would not want them making any changes themselves.

Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi left a comment

Choose a reason for hiding this comment

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

i think there's a bit of overkill in this :)

{
e.Handled = true;
var replacementValue = _hint.ReplacementTextChange!.Value;
_ = _textView.TextBuffer.Replace(new VisualStudio.Text.Span(replacementValue.Span.Start, replacementValue.Span.Length), replacementValue.NewText);
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.

still wont' work in any projection scenario.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

changed

// a space after it to make things feel less cramped.
var trailingSpace = span.Length == 0;
return new TypeHint(type, span, trailingSpace: trailingSpace);
return new TypeHint(type, span, new TextChange(displayAllSpan.Span, type.ToDisplayString(s_minimalTypeStyle)), trailingSpace: trailingSpace);
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.

it would be good to have a test to ensure that double clickong on a non-overwrite hint overwrites teh right text.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

How would you go about testing that? The testing suite we currently have has access to the InlineHInts, but not the tags themselves. If we had access to the tags we could invoke a double click on the adornment, but is there an easier way to do it? @CyrusNajmabadi

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.

well, we can have two sorts of tests. Unit tests that would validate our internal API and hte data it returns. Then an integration test that actually loads this into VS and interacts with the real tags on the editor side.

We should likely have both. Most tests should be at teh unit level, but we should have a couple of tests that actually do the full end to end validation at the editor level.

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.

this code feels like it should be in the constructor of TypeHint. Pass both spans.

@Cosifne Cosifne changed the base branch from release/dev17.1-preview1 to main September 28, 2021 04:58
@Cosifne
Copy link
Copy Markdown
Member

Cosifne commented Sep 28, 2021

Retarget this to main because 17.1 branch is not used and main is 17.1 now

{
var parameterHintUITag = InlineHintsTag.Create(
_cache[i].mappingTagSpan.Tag.Hint, Format, _textView, tagSpan, _taggerProvider, _formatMap, classify);
_cache[i].mappingTagSpan.Tag.Hint, Format, _textView, tagSpan, _taggerProvider, _formatMap, snapshot.TextBugger, classify);
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.

Suggested change
_cache[i].mappingTagSpan.Tag.Hint, Format, _textView, tagSpan, _taggerProvider, _formatMap, snapshot.TextBugger, classify);
_cache[i].mappingTagSpan.Tag.Hint, Format, _textView, tagSpan, _taggerProvider, _formatMap, snapshot.TextBuffer, classify);

{
e.Handled = true;
var replacementValue = _hint.ReplacementTextChange!.Value;
_ = _subjectBuffer.Replace(new VisualStudio.Text.Span(replacementValue.Span.Start, replacementValue.Span.Length), replacementValue.NewText);
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.

this span may be computed against a different snapshot version of hte buffer than the one currently displayed. it woudl be probably hard to hit, but this could cause a crash. You should validate that the span is still within the bounds of the buffer's current snapshot prior to making this change.

{
e.Handled = true;
var replacementValue = _hint.ReplacementTextChange!.Value;
_ = _subjectBuffer.Replace(new VisualStudio.Text.Span(replacementValue.Span.Start, replacementValue.Span.Length), replacementValue.NewText);
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.

Suggested change
_ = _subjectBuffer.Replace(new VisualStudio.Text.Span(replacementValue.Span.Start, replacementValue.Span.Length), replacementValue.NewText);
_subjectBuffer.Replace(new VisualStudio.Text.Span(replacementValue.Span.Start, replacementValue.Span.Length), replacementValue.NewText);
adornment.MouseLeftButtonDown -= Adornment_MouseLeftButtonDown;

End Using
End Function

'Protected Async Function VerifyTypeHintsDoubleClick(test As XElement, Optional optionIsEnabled As Boolean = True, Optional ephemeral As Boolean = False) 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.

:'(

IsValidType(parameter?.Type))
{
return new(parameter.Type, new TextSpan(parameterNode.Identifier.SpanStart, 0), trailingSpace: true);
if (parameterNode.Parent!.Parent.IsKind(SyntaxKind.ParenthesizedLambdaExpression))
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Would we everr have a null Parent in this case?

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 would jsut write this as:

var textChange = parameterNode.Parent?.Parent?.Kind is SyntaxKind.ParenthesizedLambdaExpression
    ? new TextChange(...)
    : null;

then just return once.

private InlineHintsTag(
FrameworkElement adornment,
ITextView textView,
ITextBuffer subjectBuffer,
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.

this feels a bit redundant. the snapshot span already points at this right? perhaps just use that so there's no chance of this being out of date?

Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi left a comment

Choose a reason for hiding this comment

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

approved, but have some small sgugestions on cleanup :)

@akhera99 akhera99 merged commit 13a91f0 into dotnet:main Jan 7, 2022
@ghost ghost added this to the Next milestone Jan 7, 2022
@RikkiGibson RikkiGibson modified the milestones: Next, 17.2.P1 Feb 4, 2022
@akhera99 akhera99 deleted the inline_hints_double_click branch June 18, 2024 20:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Double click inline adornment to insert text into document

7 participants