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

Text Snippets not available for CodeAction #592

Closed
NikolasKomonen opened this issue Nov 1, 2018 · 25 comments
Closed

Text Snippets not available for CodeAction #592

NikolasKomonen opened this issue Nov 1, 2018 · 25 comments
Labels
code actions feature-request Request for new features or functionality
Milestone

Comments

@NikolasKomonen
Copy link

NikolasKomonen commented Nov 1, 2018

From what I've seen it doesn't look like CodeAction supports snippets and defaults to plain text with no option to change it.

CompletionItem's allow snippets through the insertTextFormat property.

If there is already a way could you please let me know.

Thanks.

@rcjsuen
Copy link
Contributor

rcjsuen commented Nov 1, 2018

@NikolasKomonen Can you provide an example of the behaviour you are seeing? I'm not sure I understand your question/issue.

@angelozerr
Copy link
Contributor

@NikolasKomonen post this question because in lsp4xml we have tried to use snippet in CodeAction for xml, see this issue eclipse-lemminx/lemminx#185

@NikolasKomonen
Copy link
Author

NikolasKomonen commented Nov 1, 2018

@rcjsuen

So I am trying to apply a TextEdit though code actions. Eg I have this document:

<project>

</project>

and on the starting 'project' tag I have a code action to insert an attribute with the expected result of:

<project attName="">

</project>

In this case the TextEdit snippet I have the server sending has the text as "attName="$0"" and the
CodeAction is instead resulting in:

<project attName="$0">

</project>

This is the payload of a similar CodeAction response:

[] Received response 'textDocument/codeAction - (69)' in 2ms.
Result: [
    {
        "title": "Insert required attributes",
        "kind": "quickfix",
        "diagnostics": [
            {
                "range": {
                    "start": {
                        "line": 1,
                        "character": 1
                    },
                    "end": {
                        "line": 1,
                        "character": 10
                    }
                },
                "severity": 1,
                "code": "cvc-complex-type.4",
                "source": "xml",
                "message": "cvc-complex-type.4: Attribute 'variant' must appear on element 'resources'."
            }
        ],
        "edit": {
            "documentChanges": [
                {
                    "textDocument": {
                        "version": 8,
                        "uri": "file:///Users/fbricon/Downloads/sample-resources%203/tesst/resources.xml"
                    },
                    "edits": [
                        {
                            "range": {
                                "start": {
                                    "line": 1,
                                    "character": 10
                                },
                                "end": {
                                    "line": 1,
                                    "character": 10
                                }
                            },
                            _"newText": " variant=\"$1\""_
                        }
                    ]
                }
            ]
        }
    }
]

CompletionItem 's Responses have the insertTextFormat property that allows for snippets to be considered,
in this case 2 means 'Snippet':

[ ]Received response 'textDocument/completion - (32)' in 2ms.
Result: {
    "isIncomplete": false,
    "items": [
        {
            "label": "<?xml ... ?>",
            "kind": 10,
            "filterText": "xml version=\"1.0\" encoding=\"UTF-8\"?>",
            _"insertTextFormat": 2,_
            "textEdit": {
                "range": {
                    "start": {
                        "line": 0,
                        "character": 2
                    },
                    "end": {
                        "line": 0,
                        "character": 2
                    }
                },
                "newText": "xml version=\"1.0\" encoding=\"UTF-8\"?>$0"
            }
        }
    ]
}

@rcjsuen
Copy link
Contributor

rcjsuen commented Nov 2, 2018

@NikolasKomonen Yeah, I don't think this is expected to work. I was able to reproduce your problem in the Monaco Playground.

let uri = monaco.Uri.parse("uri://test.json");
let model = monaco.editor.createModel("xxx\nxxx\nxxx", "json", uri);

monaco.languages.registerCodeActionProvider('json', {
    provideCodeActions: function() {
        return [
            {
                title: "abc",
                edit: {
                    edits: [
                        {
                            resource: uri,
                            edits: [
                                {
                                    range: {
                                        startColumn: 1,
                                        startLineNumber: 1,
                                        endColumn: 1,
                                        endLineNumber: 1
                                    },
                                    text: "def($1)"
                                }
                            ]
                        }
                    ]
                }
            }
        ]
    }
});

monaco.editor.create(document.getElementById("container"), {
    model: model,
    language: "json",
    lightbulb: {
        enabled: true
    }
});

@rcjsuen
Copy link
Contributor

rcjsuen commented Nov 2, 2018

Oh, wow. I totally thought this was an issue in the Microsoft/monaco-editor repository! :(

In any case, I agree with your assessment that there is no way for snippets to be used in a CodeAction.

@angelozerr
Copy link
Contributor

Thanks @rcjsuen for your feedback, it should be cool if LSP could specify this feature snippet support for CodeAction.

@NikolasKomonen
Copy link
Author

@rcjsuen Thanks for the feedback

@matklad
Copy link
Contributor

matklad commented Jan 17, 2019

I need the ability to position the cursor after applying a code action as well. Using snippets for this seems like a nifty idea! To give a concrete example, I have an add derive assist for Rust, which helps with adding #[derive(Clone, Copy, PartialEq)] boilerplate.

For

struct Foo {
   field: ()|
}

It should result in

#[derive(|)]
struct Foo {
    field: ()
}

It also should work when the derive already exists, and in this case it only should move the cursor.

#[derive(Clone)]
struct Foo {
    field: ()|
}

=>

#[derive(Clone|)]
struct Foo {
    field: ()
}

@heejaechang
Copy link

@dbaeumer any plan to support this? are you open to this feature request such as accepting contribution?

@dbaeumer
Copy link
Member

@heejaechang defining this in the spec is the easy part. We need a client implementation as well and at least VS Code has no support for this right now.

@matklad
Copy link
Contributor

matklad commented Jan 25, 2021

FWIW, in rust-analyzer we implement this already via a protocol extension and a hacky vscode impl:

Some other clients implement this extension as well, for example, lsp-mode

@heejaechang
Copy link

heejaechang commented Jan 25, 2021

@matklad thank you, I will take a look! @dbaeumer even though it is not supported by any client yet, would be nice if it is at least in spec, so some client can support it.

@dbaeumer
Copy link
Member

@heejaechang we decided that we only add something to the spec if we have an implementation in a client. Otherwise things are hard to spec and to get feedback on.

@michaelmesser
Copy link
Contributor

I'm confused. Is lsp-mode not a client?

@KamasamaK
Copy link
Contributor

@dbaeumer said

@heejaechang defining this in the spec is the easy part. We need a client implementation as well and at least VS Code has no support for this right now.

VS Code now supports this since v1.72. See microsoft/vscode#145374

@dbaeumer
Copy link
Member

Something to work on for 3.18.

@dbaeumer dbaeumer removed this from the Backlog milestone Oct 21, 2022
@heejaechang
Copy link

@dbaeumer can you make sure SnippetTextEdit is allowed all places where LSP returns TextEdit not just workspace edits? things like "FormatOnType" which returns TextEdit[].

thank you!

@rchiodo
Copy link

rchiodo commented Nov 10, 2022

If this was supported for all TextEdits, it would make it possible for us to implement this feature for pylance:
microsoft/pylance-release#2615

Without it, the cursor comes out weird.

@heejaechang
Copy link

@jrieken how about other places where TextEdit is used in vscode api such as provideOnTypeFormattingEdits, provideDocumentRangeFormattingEdits and more? shouldn't all they support SnippetTextEdit?

@jrieken
Copy link
Member

jrieken commented Dec 2, 2022

@heejaechang not yet decided. Your case is valid but generally full blown snippets while users type could be asking for trouble. E.g snippets can force you into an interactive mode, e.g have you to select a choice element, have multiple placeholders, etc pp. Having this happen while I type along (or on save) doesn't seem like a good idea.

... this feature for pylance: microsoft/pylance-release#2615

Can't you do something like @meganrogge has done with https://marketplace.visualstudio.com/items?itemName=meganrogge.template-string-converter. AFAIK this isn't a format-on-type provider but just a typing listener

@rchiodo
Copy link

rchiodo commented Dec 2, 2022

@jrieken thanks for the suggestion. We were holding Megan's solution as a last resort because it requires a lot of work in the extension (whereas the language server already has this information). So, the hope was to be able to just change selection as part of the edits returned from the provideDocumentRangeFormattingEdits.

@jrieken
Copy link
Member

jrieken commented Dec 5, 2022

because it requires a lot of work in the extension (whereas the language server already has this information)

Understood, I would still implement the logic in the language server but with a custom route/message that the extension invokes when certain things happen.

@deakjahn
Copy link

Another use case for them is refactoring code actions. Say, I have a code action that converts a foreach loop into a for loop. During refactoring, I introduce a new index variable that I'd need to allow the user to rename in snippet edit mode. Yes, I do it now by sending it back to the client and doing it from there. Possible but not really elegant, snippets should be supported everywhere.

@puremourning
Copy link

Doesn’t need to be a snippet. Could be an argument (like rename). Snippets are not a panacea of ux

github-merge-queue bot pushed a commit to leanprover/lean4 that referenced this issue Dec 20, 2023
# Summary

This makes a small addition to our take on the LSP protocol
in the form of supporting snippet text edits.
It has been discussed
[here](microsoft/language-server-protocol#592)
on the LSP issue tracker for a while,
but seems unlikely to be added anytime soon.
This feature was requested by @PatrickMassot for the purposes
of supporting Lean code templates in code actions and widgets.

---------

Co-authored-by: David Thrane Christiansen <[email protected]>
@dbaeumer
Copy link
Member

dbaeumer commented Jul 8, 2024

This got implemented for 3.18 be having snippet support in WorkspaceEdits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
code actions feature-request Request for new features or functionality
Projects
None yet
Development

No branches or pull requests