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

Fix completion on part of existing string #1941

Merged
merged 5 commits into from
Sep 28, 2020

Conversation

nohwnd
Copy link
Contributor

@nohwnd nohwnd commented Sep 14, 2020

When completion re-uses part of existing string the proposed change should re-use the part of the string in the original span and commit the change.

Fix dotnet/vscode-csharp#4063

@nohwnd
Copy link
Contributor Author

nohwnd commented Sep 14, 2020

The completion does not handle correctly the case when completion keeps a bit of the original text. It works with one, because the typed text is on the given position 34, 45 (line, col) the returned change would be OnEnabled()\n ... with position 34, 45. But with One the change is Enabled()\n ... on position 34,47.

This will skip this condition and instead use the one the is more complicated, that allows overwriting the existing code, but that path does not support this case correctly.

if (typedSpan == change.TextChange.Span)
{
(insertText, insertTextFormat) = getAdjustedInsertTextWithPosition(change, position, newOffset: 0);
break;
}

I was able to naively fix it by just taking the start of the typedText and prepending it to the proposed change. But this seems like oversimplifying the problem.

@filipw
Copy link
Member

filipw commented Sep 14, 2020

can you add some tests that reproduce this issue?


(insertText, insertTextFormat) = getAdjustedInsertTextWithPosition(change, position, newOffset: 0);

insertText = prefix + insertText;
Copy link
Member

Choose a reason for hiding this comment

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

what about a situation where insertText should correct the letter casing of the typed text?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would that be triggered in this case? I don't think it will because that is covered by the if above this one, then then typedSpan is replaced as a whole. In this case the part of the span is already correct so the suggestion only contains the part that needs to be added. At least that is what I saw when trying one<tab> vs One<tab>. In the first case one gets OnEnabled() ... suggestion, but One gets Enabled() ... suggestion. The span of the first suggestion is identical to the typedSpan, while the span of the second suggestion starts 2 characters after th typedSpan, because you already have On in the text.

@nohwnd
Copy link
Contributor Author

nohwnd commented Sep 14, 2020

@filipw

can you add some tests that reproduce this issue?

Yeah, sure. I could not find where this is tested originally, because I was looking for CompletionService, but now I see there is CompletionFacts.

@JoeRobich
Copy link
Member

@333fred Maybe you have some thoughts on how we could handle this.

@333fred
Copy link
Contributor

333fred commented Sep 14, 2020

I think the correct way to handle this is to use a TextEdit for the change, rather than use insert text. When I implemented this originally, I missed the part of the LSP spec that stated InsertTextFormat applied to both the text in InsertText and the text in a TextEdit. So, the best thing to do is to just have the main insertion be a TextEdit that specifies the exact span that should be replaced, including the current cursor location, rather than trying to fix up the insert text for different casing.

Because I misread the LSP spec when imlementing completion, I didn't realize that InsertTextFormat applied to both InsertText, and to the NewText property of the main TextEdit of a completion item. This latter version is much more robust to casing issues than using InsertText directly, and ensures that matching of completion items in the completion list works better as well. Fixes dotnet/vscode-csharp#4063.
@333fred
Copy link
Contributor

333fred commented Sep 18, 2020

@nohwnd I opened nohwnd#1 against your branch. I believe that it's a more robust implementation that will ensure that future errors like this are taken care of by explicitly providing the range of text to be replaced by the main edit.

333fred added a commit to 333fred/vscode-csharp that referenced this pull request Sep 18, 2020
This is the vscode side of OmniSharp/omnisharp-roslyn#1941. This is written in such a fashion as to be mergeable now, as it will fall back to InsertText if TextEdit is not present in the completion response. After some appropriate period of time, we can remove the InsertText component.
// completion and typing `EQ` will bring up the Equals override, but then dismissing and
// reinvoking completion will have a range that just replaces the Q. Vscode will then consider
// that capital Q to be the start of the filter text, and filter out the Equals overload
// leaving the user with no completion and no explanation
Copy link
Contributor

@333fred 333fred Sep 18, 2020

Choose a reason for hiding this comment

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

Technically, vscode does have an API to deal with this inconsistency. But it's not in the lsp spec, only in the native vscode completion handler api, so we can't use it here.

@nohwnd
Copy link
Contributor Author

nohwnd commented Sep 18, 2020

@333fred Thanks, that's perfect.

JoeRobich pushed a commit to dotnet/vscode-csharp that referenced this pull request Sep 18, 2020
This is the vscode side of OmniSharp/omnisharp-roslyn#1941. This is written in such a fashion as to be mergeable now, as it will fall back to InsertText if TextEdit is not present in the completion response. After some appropriate period of time, we can remove the InsertText component.
@333fred 333fred mentioned this pull request Sep 26, 2020
@filipw filipw merged commit a44adb4 into OmniSharp:master Sep 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Error in autocompletion with strings starting with an uppercase letter
4 participants