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

Why is java.signatureHelp disabled by default? #2063

Closed
fvclaus opened this issue Aug 16, 2021 · 6 comments
Closed

Why is java.signatureHelp disabled by default? #2063

fvclaus opened this issue Aug 16, 2021 · 6 comments

Comments

@fvclaus
Copy link
Contributor

fvclaus commented Aug 16, 2021

I had a shortcut assigned to Trigger parameter hints which I always used when editing Typescript or Javascript files. I didn't work while editing Java files, and therefore I assumed that this extension does not support parameter hints. Why else would it not work? I did not take me too long to find this setting, but only because my when expression was assigned to editorHasSignatureHelpProvider which hinted me to LSP and I eventually stumbled over the setting by looking at the LS log and searching for signatureHelp inside the source code of this extension.

Why is this not enabled by default? Users coming from Typescript (or other languages) where this is enabled by default will probably not think about looking for a setting to activate it.

@fbricon
Copy link
Collaborator

fbricon commented Aug 16, 2021

Because Java completion already provides all overloaded signatures (contrary to Typescript), we found that enabling signatureHelp by default was more annoying than not.

@fvclaus
Copy link
Contributor Author

fvclaus commented Aug 17, 2021

When you say annoying, do you mean that the parameter hints and code completion is visible at the same time?
vscode_signatureHelp_enabled_both

Overloaded signatures are available in the parameter hint popup. The parameter hint has up and down navigation arrows in the lower left corner to navigate through the different signatures:

Overloaded signature 1
vscode_signaturehelp_1of2
Overloaded signature 2
vscode_signaturehelp_2of2

There are even keyboard shortcuts for navigating:

  • showNextParameterHint assigned to Alt+Down on my machine
  • showPrevParameterHint assigned to Alt+Up on my machine

Would it be possible to hide the code completion when the parameter hint is visible? Code completion is inferior to parameter hints: It does not hightlight the current parameter and can only display a limited number of parameters. In the first screenshot, the overloaded constructor with only 4 parameters could already not be displayed entirely. This would also align more closely with the way the Typescript completion works.

@fvclaus
Copy link
Contributor Author

fvclaus commented Sep 3, 2021

I looked into this a little bit and changed the language server to not return completions inside functions and constructors. This does not work in most cases, because vscode will only call document/completion under certain circumstances. If you type ArrayL and ask for completion, vscode will only ask the language server once and filter the CompletionItems as the user types.

arraylist_completion

I tracked down the code inside vscode that controls when the CompletionItemProvider is called:
https://github.com/microsoft/vscode/blob/fc1a1e8f13af4fcf9c5b60e0a24bd14074f8c810/src/vs/editor/contrib/suggest/suggestModel.ts#L330

This seems like a good idea and means that this cannot be solved by returning different CompletionItems depending on the cursor position.

Next I tried to align the language server completions more closely with Typescript. Typscript will provide a completion stringify at JSON.st. In JS, that actually makes sense, because JSON.stringify would be a valid reference to a function. After pressing ( only the parameter hint appears. Providing a completion ArrayList in Java does not make sense, because new ArrayList or myString.substring is not valid Java. Despite these problems, I tried to work with this for a few days and can conclude that it lowers productivity quite noticably. The problem is not typing the extra (. What gets lost is the TextEdit that will insert the parameters with the ability to tab through them:
parameter_without_tab

In contrast to the default:
parameter_with_tab

I will try to open a enhancement propals on vscode or the language server spec. I think a combination of the two: Selecting a completion with parameters and automatically opening parameter hints would probably be a better solution.

@Eskibear
Copy link
Contributor

Eskibear commented Sep 8, 2021

For the issue that candidate list remains open, I can think of several solutions:

filterText

/**
* A string that should be used when filtering a set of
* completion items. When falsy the label is used as the
* filter text for this item.
*/
filterText?: string;

Set a proper filterText can possibly work. E.g. label is "substring(int index)" and filterText is "substring".

commitCharacters

/**
* An optional set of characters that when pressed while this completion is
* active will accept it first and then type that character. Note that all
* commit characters should have length=1 and that superfluous characters
* will be ignored.
*/
commitCharacters?: string[];

According to the spec, if we add ( as a commit character, it might commit the item when you input (. But maybe we have to change the text to insert. E.g. for item "substring(int index)", use "substring" as the insertText or textEdit.newText, instead of the whole signature.

CompletionItemLableDetails

CompletionItemLabelDetails will be in LSP 3.17, might be an option to improve the experience.

@fvclaus
Copy link
Contributor Author

fvclaus commented Sep 13, 2021

filterText works great:

public CompletionItem toCompletionItem(CompletionProposal proposal, int index) {
    $.setFilterText(new String(proposal.getName()));
    ...
}

java_completion_filter

commitCharacters does not work with the current textEdit as expected by @Eskibear. Instead of "substring(${1:beginIndex}, ${2:endIndex})", it probably must be substring, because the commitCharacter will be added at the end. With the example above, the first paramter will be enclosed in brackets:

public CompletionItem toCompletionItem(CompletionProposal proposal, int index) {
    $.setCommitCharacters(Collections.singletonList("("));
    ...
}

java_completion_commitcharacters

@jdneo
Copy link
Collaborator

jdneo commented Feb 21, 2022

I think currently there is another behavior which is confusing.

The selected completion item is different from the content provided by signature helper:

signature-helper.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants