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

Add optionalReplacementSpan to completions response #40347

Merged
merged 6 commits into from
Sep 4, 2020

Conversation

andrewbranch
Copy link
Member

Closes #35602

Adds a top-level property optionalReplacementSpan to CompletionsInfo, which contains the TextSpan representing the identifier or string literal-like content where completions were completions were requested, if they were requested on such a node. E.g. when requesting completions at the caret in

console.clockwork
//        ^

the optionalReplacementSpan will be the span of the identifier clockwork. The editor can opt to use this span when accepting the completion entry clear to produce console.clear instead of console.clearockwork, as it would today. The span is also populated for string literal completions:

Array["toSpaghetti"]
//        ^

The optionalReplacementSpan here is the span of toSpaghetti, excluding the quotes.

As before, if an individual CompletionEntry specifies a replacementSpan, that span must be used. It is possible for an optionalReplacementSpan to be populated even when some individual entries have a replacementSpan that must receive priority.

@typescript-bot
Copy link
Collaborator

Thanks for the PR! It looks like you've changed the TSServer protocol in some way. Please ensure that any changes here don't break consumers of the current TSServer API. For some extra review, we'll ping @sheetalkamat, @amcasey, @mjbvz, @minestarks for you. Feel free to loop in other consumers/maintainers if necessary

@typescript-bot typescript-bot added Author: Team For Milestone Bug PRs that fix a bug with a specific milestone labels Sep 1, 2020
@andrewbranch andrewbranch requested a review from mjbvz September 1, 2020 20:14
Copy link
Contributor

@mjbvz mjbvz left a comment

Choose a reason for hiding this comment

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

The protocol changes look good to me

// @lib: dom

//// console.[|cl/*0*/ockwork|];
//// type T = Array["[|toS/*1*/paghetti|]"];
Copy link
Member

Choose a reason for hiding this comment

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

I am not sure why this has to be optionalReplacementSpan and not just replacementSpan if editor supports it (there is already preference for that no)

Copy link
Member Author

Choose a reason for hiding this comment

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

My understanding is there is not a preference that allows users to opt out of using replacementSpan—in VS and VS Code, the presence of replacementSpan means the editor will always use it, which is good because it means users can’t end up in a situation where they trigger completions on style.| and end up with a syntax error like style.["background-color"]. This new span will be configurable by a preference.

That said, it does seem like using the new optionalReplacementSpan is almost always better than the current behavior, but I guess @mjbvz and co. have thought through the reasons someone might want to have both options more than I have.

Copy link
Member

Choose a reason for hiding this comment

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

But i dont see this being configured by preference? Even if this is configured by preference, why cant it be returned as part of replacementSpan since replacement span if present is always meant to override this one?

Copy link
Member Author

Choose a reason for hiding this comment

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

I believe it’s supposed to be an editor preference, which could potentially be configured across multiple languages. If TS Server adopted this preference and VS Code sent it to us, that would be an option. That’s not something that was discussed in the issue; I personally don’t have strong feelings one way or another. I’ll let @mjbvz weigh in.

Copy link
Contributor

@mjbvz mjbvz Sep 4, 2020

Choose a reason for hiding this comment

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

VS code lets users configure how suggestions are inserted using the editor.suggest.insertMode setting. The options are insert which always inserts the current suggestion without replacing the suffix, and replace which would try replacing the suffix word.

However users can always toggle to the opposite mode of the current one by holding down shift while accepting a completion. This means that TS always needs to return both spans to us in some way. I think we need a clear distinction between:

  • Here's a span that should always be replaced regardless of insert mode (the current replacementSpan property)
  • Here's a replacement span that you should use if the user accepts a completion in replace mode (which would be the new optionalRepalcementSpan)

I think the current proposal covers our needs but let me know if that doesn't sound correct based on my description

Copy link
Member

Choose a reason for hiding this comment

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

Got it. Now understand why you always want this property to be populated and separate. Thanks.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the clarification 👍

@andrewbranch andrewbranch merged commit f6f2d36 into microsoft:master Sep 4, 2020
@andrewbranch andrewbranch deleted the feature/35602 branch September 4, 2020 20:14
* this span or its default one. If `CompletionEntry["replacementSpan"]` is defined, that span
* must be used to commit that completion entry.
*/
optionalReplacementSpan?: TextSpan;
Copy link

@jasonwilliams jasonwilliams Nov 19, 2021

Choose a reason for hiding this comment

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

@andrewbranch is this correct? The examples above in the unittests show TextSpan being used. But this is pointing to here, is it using the correct interface?

Copy link

@jasonwilliams jasonwilliams Nov 19, 2021

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, internally it should be a ts.TextSpan and over the wire it should be a ts.server.protocol.TextSpan. The conversion is done on the way out in session.ts. It’s possible we’re missing a conversion somewhere but the types are right. What’s going on?

Copy link

@jasonwilliams jasonwilliams Nov 19, 2021

Choose a reason for hiding this comment

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

What’s going on?

im having a nightmare with a typescript server plugin not having correct completion data, mainly range data, see here microsoft/vscode#134328

I thought maybe it needs to include This new field but TextSpan didn’t match with the examples here

Choose a reason for hiding this comment

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

I though the culprit was here https://github.com/microsoft/typescript-styled-plugin/blob/main/src/_language-service.ts#L121-L138 because item has the range, but its never converted. But the types seem correct.

Looking at the types for CompletionEntry and CompletionEntryDetails I don't see where the range would be passed through back to VSCode

Copy link
Member Author

Choose a reason for hiding this comment

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

Here’s where it gets converted on its way to VS Code

optionalReplacementSpan: completions.optionalReplacementSpan && toProtocolTextSpan(completions.optionalReplacementSpan, scriptInfo),

Copy link

@jasonwilliams jasonwilliams Nov 20, 2021

Choose a reason for hiding this comment

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

Thanks Andrew.
I don’t suppose you know of any typescript plugin that sets this? I’ve burnt out trying to find a solution for here. I’ve struggled to get the information of the token the cursor is setting next too (like offset and length).

Choose a reason for hiding this comment

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

@andrewbranch in case you were curious, this was the fix, took me days: microsoft/typescript-styled-plugin#156

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Author: Team For Milestone Bug PRs that fix a bug with a specific milestone
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add inserting/replacing range to suggestion items
7 participants