VSCode extension: disable repeating things in code completion - visual-studio-code

I am creating a language extension for VSCode using Java and the LSP4J library. It is something like this.
But I have a problem - if the user presses Ctrl+Space, and the language server returns an empty list, VSCode will still offers its options - things that are already in the code. How can I get it to display something like "No suggestions" instead?

The text-based completion you're seeing there can be disabled with the "editor.wordBasedSuggestions" setting.
Extensions can change the default value of a setting for a particular language by contributing configurationDefaults in package.json:
"contributes": {
"configurationDefaults": {
"[lang]": {
"editor.wordBasedSuggestions": false
}
}
}
Where lang is the ID of the language in question.

If the language server sends back an empty list you could add an artificial entry with text: "No suggestions" to the completion list.

Related

VsCode Extension custom CompletionItem disables built-in Intellisense

I am working on a VsCode extension in that I want to provide custom snippets for code completion.
I know about the option of using snippet json files directly, however those have the limitation of not being able to utilize the CompletionItemKind property that determines the icon next to the completion suggestion in the pop-up.
My issue:
If I implement a simple CompletionItemProvider like this:
context.subscriptions.push(
vscode.languages.registerCompletionItemProvider(
{scheme:"file",language:"MyLang"},
{
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {
let item = new vscode.CompletionItem('test');
item.documentation = 'my test function';
item.kind = vscode.CompletionItemKind.Function;
return [item];
}
}
)
)
then the original VsCode IntelliSense text suggestions are not shown anymore, only my own. Should I just return a kind of an empty response, like
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {
return [null|[]|undefined];
}
the suggestions appear again as they should. It seems to me that instead of merging the results of the built-in IntelliSense and my own provider, the built-in ones get simply overridden.
Question:
How can I keep the built-in IntelliSense suggestions while applying my own CompletionItems?
VsCode Version: v1.68.1 Ubuntu
I seem to have found the answer for my problem, so I will answer my question.
Multiple providers can be registered for a language. In that case providers are sorted
by their {#link languages.match score} and groups of equal score are sequentially asked for
completion items. The process stops when one or many providers of a group return a
result.
My provider seems to provide results that are just higher scored than those of IntelliSense.
Since I didn't provide any trigger characters, my CompletionItems were comteping directly with the words found by the built-in system by every single pressed key and won.My solution is to simply parse and register the words in my TextDocument myself and extend my provider results by them. I could probably just as well create and register a new CompletionItemProvider for them if I wanted to, however I decided to have a different structure for my project.

Is there anyway to check inactive terminalEditors in when arg in keybindings.json in VScode?

I want to createTerminalEditor if there is no terminalEditor opened yet.
Note: I'm talking about terminalEditor and not terminal.
So, I'm looking for a when arg which says something like editorAlreadyExists != terminalEditor, just like there is activeEditor which aceepts string of terminalEditor.
Is there anyway to achieve this?
Here is activeEditor example for reference, but I want to check if terminalEditor exists in all the already opened editors, not just a activeEditor.
{
"key": "ctrl+`",
"command": "workbench.action.createTerminalEditor",
"when": "activeEditor != terminalEditor"
},
I see that there is a when clause for:
terminalEditorFocus: true/false
which doesn't look like it would help except for the fact that it isn't in the list (via Developer: Inspect Context Keys) at all when there is no terminal editor open. So I thought maybe there was a keybinding when clause that could exploit this. But I tried all kinds of thing, like whether it was null or undefined or the empty string or neither true nor false, etc. but nothing worked. I think if the key terminalEditorFocus doesn't exist, then nothing at all is delivered to the keybinding resolver and it always fails.
You could file an issue asking for a specific terminalEditorExists sort of when clause.
There will be another way. There is a presently experimental api to access all the open tabs. See proposed api. So you could write an extension that checks all the open tabs and fires the workbench.action.createTerminalEditor command if none are a terminalEditor. It works right now in the Insiders Build, but when it will go final I don't know - it seems pretty solid now. Issue: Tab Model API.
const tabs = vscode.window.tabs;
const openTerminalEditor = tabs.some(tab => tab.viewId === 'terminalEditor'); // true/false
Then you could either set your own context key with setContext or run the command.

Go to definition, go to implementation, autogenerate import for Ember

Im using Ember with VS Code.
What I need is to generate import string on a fly when I encounter dependency. For example I write someting like:
#tracked isLarge = false;
But I don’t have “#tracked” imported yet. So the otion could be to set the coursor on #tracked, press something like “Action + .” and pick “generate import”. It should generate import string:
import { tracked } from '#ember/tracking';
But it doesn’t work out of the box. How can I do that?
UPDATE: the same question about:
go to definition
go to implementation
cmd+click to navigate to implementation/component
You can use the extension My Code Actions
You can create actions that just insert the text independent of an error.
"my-code-actions.actions": {
"[javascript]": {
"import tracked": {
"where": "insertAfter",
"insertFind": "^import",
"text": "import { tracked } from '#ember/tracking';\n"
}
}
}
The key combo to use is the Code Action combo: Ctrl+.
If you get a diagnostic (PROBLEM panel, and squiggle) you can use that to further customize the action and you can use text from the diagnostics message.
I'm current adding the possibility to make multiple edits in an action and to use further customization and generalization.
"Ember Language Server" brings some solution. But it works mostly with library code that has .d.ts typings.
In case of custom JS code it still doesn't work.
So there is no straight solution. Only 2 ways:
Write .d.ts typing for custom code JS files
Move project to typescript

How can I configure multiple formatters to run in a sequence on save in VSCode?

I am working on a Haskell project that must be formatted by both:
stylish-haskell (for import reordering)
brittany (for general formatting)
I can set the single default formatter for a language:
"[haskell]": {
"editor.defaultFormatter": "MaxGabriel.brittany"
}
or I can select one from a list using editor.action.formatDocument.multiple ("Format Document With... in the command palette).
But I need to run both of them, one after the other, on save. As of right now, I can only run the single default formatter on save. The order doesn't matter in this case, but it could in more general cases.
I've tried setting editor.defaultFormatter to a list of formatters (this didn't work, as expected) and built a local extension that calls editor.action.formatDocument.multiple with various arguments, which just brings up a drop-down list of available formatters to choose from.
How can I run both formatters sequentially on save?
I don't think this is really a use case that is officially supported, but you could possibly work around it by having an extension do the following:
disable "editor.formatOnSave" for Haskell
register a callback for vscode.workspace.onDidSaveTextDocument, in which you:
set "editor.defaultFormatter" to the first formatter using the WorkspaceConfiguration API
call "editor.action.formatDocument"
set "editor.defaultFormatter" to the second formatter
call "editor.action.formatDocument" again
Of course, this only covers formatOnSave formatting, not formatOnPaste or formatOnType.
It's a bit late but, for newcomers, you can also use one extension that is already created... and it's thanks to all the answers of this post, by the way.
See Multi Formatter
So you can just add the formatters you want to run in the settings.json or the *.code-workspace settings like this:
{
"[haskell]": {
"editor.defaultFormatter": "Jota0222.multi-formatter",
"editor.formatOnSave": true
"multiFormatter.formatterList": [
"vigoo.stylish-haskell",
"MaxGabriel.brittany"
],
}
}
With that configuration, stylish-haskell will run first and Britanny will run just after once you save the changes.
P.S.: I'm indeed the author of the solution. I'm not aiming to do any promotion, it's just an implementation of the answers above. So I'll like to thank the people that answered before me.
Also, the extension is open sourced, feel free to check the code and contribute on GitHub
Last thoughts: look at Run on Save extension and execute your formatters not as extensions but as scripts.
Previous edit:
If your formatter doesn't contribute a command (see discussion in comments for some that do) as it appears brittany does not, try something like this for its task:
{
"label": "brittany format step",
"type": "shell",
"command": "brittany ${file}",
"problemMatcher": []
}
From Gama11's answer of creating a VSCode extension:
The following code specifies the formatter and then formats the code.
const config = vscode.workspace.getConfiguration('editor', vscode.window.activeTextEditor?.document);
await config.update('defaultFormatter', 'MaxGabriel.brittany');
await vscode.commands.executeCommand('editor.action.formatDocument');
Therefore, the answer is:
const config = vscode.workspace.getConfiguration('editor', vscode.window.activeTextEditor?.document);
const formatters = ['MaxGabriel.brittany', 'ms-python.python'];
formatters.forEach(async formatter => {
await config.update('defaultFormatter', formatter);
await vscode.commands.executeCommand('editor.action.formatDocument');
});

Where are the docs on how to add symbol support for a language to Visual Studio Code?

I would like to add symbol support for PowerShell to VS Code but I'm not finding any docs on the code.visualstudio.com/docs site.
Also, is it possible to do this for a language like PowerShell that, for the moment, will only work on Windows? Is there a way to light up symbol support on Windows only?
BTW I've added a bunch of PowerShell snippets that I'm in the process of trying to get integrated into VS Code. Any help on how to get these snippets into the product would be appreciated as well? I did submit an issue on the snippets, suggesting that the team put these into VS Code.
There is currently no documentation for the plugin API. It's too early for this as the API is still changing with every minor release. The VSCode team is focused on providing a stable plugin API. There will be a documentation about it when it's done.
Nevertheless it is already possible to add a new language plugin or extending an exisiting one. Take a look on this short description on how to add declaration support for a new language: Create Custom Language in Visual Studio Code
You could add symbol support in a similar way. What you need is something like an abstract syntax tree builder for powershell scripts and an application or a javascript module that is able to process a JSON request in order to provide the correct symbols. An example request for outline support is this:
{
"seq":442,
"type":"request",
"command":"navbar",
"arguments":
{
"file":"c:/Users/C/Documents/projects/MyProject/MyFile.xxx"
}
}
A response could look like that:
{
"seq":442,
"type":"response",
"command":"navbar",
"request_seq":442,
"success":true,
"body":[
{
"text":"TObjA",
"kind":"class",
"kindModifiers":"",
"spans":[
{
"start":{
"line":10,
"offset":3
},
"end":{
"line":16,
"offset":4
}
}
],
"childItems":[
]
},
{
"text":"DoSomething",
"kind":"method",
"kindModifiers":"",
"spans":[
{
"start":{
"line":20,
"offset":1
},
"end":{
"line":27,
"offset":4
}
}
],
"childItems":[
]
},
]
}
I'm not sure what do you mean with "symbol support". Is it something like "jump to symbol inside the current file" using CTRL+Shift+O? Then you are looking for outlineSupport.
Is it something like "find a symbol in any file" using CTRL+P, #? Then you are looking for navigateTypesSupport.
Copy the needed .js file from the vs.langauage.csharp.o folder to the vs.langauage.powershell folder and register the support in powershellMain.js as it is done in omnisharpMain.js.
If you want to register the new support only on Windows then you can do it like this:
var isWin = /^win/.test(process.platform);
if(isWin)
monaco.Modes.NavigateTypesSupport.register('powershell', new navigateTypesSupport_1.default(ModelService, server));
I hope this helps for the moment. Don't forget to save your changed plugins in a different folder. VSCode often deletes changes in the plugin folders on update.