Search code examples
javascriptvisual-studio-codevscode-extensions

Not getting suggestions in vs code for newly created extension


My code is as follows:

/**
 *  Input auto-completion provider
 */
class InputAutoCompletionProvider {
  // eslint-disable-next-line class-methods-use-this
  provideCompletionItems(document, position) {
    const lineAt = document.lineAt(position);
    const lineText = document.getText(lineAt.range);

    const searchText = getSearchText(lineText, position);

    const items = [];
    // console.log('lineAt', lineAt);
    // console.log('lineText', lineText);
    // Add the actual typed text to suggestions list
    const item = new vscode.CompletionItem(kh2dev(searchText));
    item.sortText = String(0);
    console.log(item);
    items.push(item);

    return items;
  }
}

module.exports = InputAutoCompletionProvider;

The rest is hosted at github

The intention is run the transliteration and show it in suggestions. The objective is to select that transliteration in the suggestion to replace the word.

I can get the right output in the console while debugging but not in the suggestions tooltip while activating the extension.


Solution

  • I cloned your repo and worked it out.

    Short answer: Add this to your code:

        item.filterText = searchText;
        item.preselect = true;  // this sometimes helps
    

    Longer answer:

    I remembered that sometimes you have to add a CompletionItemRange.range even if you think the default would work. So I tried

    item.range  = new vscode.Range(position, position);
    

    and indeed, now your desired completions do show up. But they are put at the very end of the suggestions so one would usually have to scroll to see them. And worse, selecting them only put them at the cursor position - it did not replace the letter that triggered the completion. That probably isn't what you wanted.

    I found this GitHub issue: CompletionItems and ranges not working. Here is the relevant part in full:

    A completion item provider is invoked, returns completions but they don't show up! 😕 What's the issue? Filtering! Filtering compares completions with a prefix and hides those that don't match.

    Example
    • trigger completions here: say.he| (| is the cursor)

    • provider returns abc, help, hood

    • the editor takes the he-prefix and scores it against abc, help, and hood.

    • scoring yields these result:
      abc - no match, don't show
      help - good match, show
      hood - no match, only h occurs, don't show

    • editor shows help suggestion, does not show abc and hood suggestion

    Extensions Rule!

    The above sample was using "defaults" to determine the prefix and the filter criteria.

    • prefix: each completion can define its very own prefix via vscode.CompletionItem#range. Taking the example above, valid prefixes can be say.he or .he or `` (the empty string). Any range is valid as long as it includes the cursor position and is single line only.

    • filter: each completion can define what string to use when filtering. The default is the label but via vscode.CompletionItem#filterText any string can be defined

    When to use what? It depends on the language, its word definition, and if you control/understand the word definition or not. The defaults usually work well enough but some languages might use a non-intuitive word definition, or completions span multiple words, or completions include non-word character etc. In all those cases the range-property should be used.

    I examined the suggestion score of your completions. Select one of your suggestions and Ctrl+/. I use this keybinding in the DEMO below.

    Your completions had a score of -100 no surprise why it was put at the end of all suggestions. But it had no prefix value at all which explains why accepting the completion did not replace the current letter that triggered it.

    Reading through the above GH quote implies using either item.filter or setting a prefix. But there is no prefix property - you set the prefix by setting the range. I had already tried setting the range and while it did show the completion it didn't actually replace the trigger letter.

    So I tried

    item.filterText = searchText;

    Now that sets the prefix to the trigger character, say a and the score is much higher since the prefix is being matched against the leading word which is also the trigger character.

    IMPORTANT

    Using * as the DocumentSelector in registerCompletionItemProvider() does not work for me. If you want to target all files this does seem to work but for performance reasons you should list the fileTypes if possible rather than targeting them all:

            const provider = new InputAutoCompletionProvider();
            disposableProvider = vscode.languages.registerCompletionItemProvider(
              // '*',    // doesn't work
              { pattern: '**/' },   // does target different filetypes
              provider,
               .......
    

    Here is a demo:

    completions with filterText