sublimelsp / LSP

Client implementation of the Language Server Protocol for Sublime Text
https://lsp.sublimetext.io/
MIT License
1.65k stars 182 forks source link

Rust: Format selection disabled in context menu but Format document is not #1414

Closed detly closed 3 years ago

detly commented 4 years ago

Sublime Text 3 (Build 3211) Rust enhanced: v2.22.0 RLS: rls 1.41.0 (9bfb47a 2020-10-05) LSP: v0.13.1 OS: Ubuntu 20.04

I have LSP and Rust Enhanced installed via Package Control, and the stable and beta releases of RLS installed via Rustup. I do not have Cargo etc. on my system path, but I have added:

    "clients":
    {
        "rls":
        {
            "command": ["~/.cargo/bin/rustup", "run", "beta", "rls"],
        }
    },

...to my LSP user settings.

Expected behavior

Both Format document and Format selection should be enabled in the context menu.

Actual behavior

Format document is enabled. Format selection is not.

The fact that Format document is enabled and works makes me think that LSP and RLS are communicating fine, but there's a capability missing or something like that.

Here's some console messages (I removed what I thought was from unrelated plugins, let me know if you want that too):

LSP: global configs ['flow=False', 'jdtls=False', 'haskell-ide-engine=False', 'erlang-ls=False', 'intelephense-ls=False', 'lsp-tsserver=False', 'dart=False', 'rlang=False', 'elixir-ls=False', 'ruby=False', 'javascript-typescript-langserver=False', 'pyls=False', 'cquery=False', 'golsp=False', 'reason=False', 'gopls=False', 'rls=False', 'polymer-ide=False', 'rust-analyzer=False', 'sourcekit-lsp=False', 'clangd=False', 'vscode-css=False', 'typescript-language-server=False', 'sorbet=False', 'bashls=False', 'phpls=False', 'ocaml=False']
LSP: applying .sublime-project override for rls
LSP: group 0 view /home/jason/Code/td-aseconf/src/lib.rs
LSP: window 2 starting 1 initial views
LSP: applying .sublime-project override for rls
LSP: window 2 requests rls for /home/jason/Code/td-aseconf/src/lib.rs
LSP: starting ['/home/jason/.cargo/bin/rustup', 'run', 'beta', 'rls']
LSP: window 2 added session rls
LSP: single folder session: /home/jason/Code/td-aseconf
LSP: rls: Supported execute commands: ['rls.applySuggestion-71626', 'rls.deglobImports-71626']
LSP: rls: registering capability: didChangeWatchedFilesProvider
Unable to open /home/jason/Code/config-st3/Packages/Rust Enhanced/RustEnhanced.sublime-settings
reloading settings Packages/User/RustEnhanced.sublime-settings
LSP: found ready session rls for /home/jason/Code/td-aseconf/src/main.rs
LSP: applying .sublime-project override for rls
LSP: found ready session rls for /home/jason/Code/td-aseconf/src/main.rs
Unable to open /home/jason/Code/config-st3/Packages/LSP/LSP.sublime-settings

I honestly don't know what Unable to open /home/jason/Code/config-st3/Packages/LSP/LSP.sublime-settings is doing there, since LSP works fine. Unable to open /home/jason/Code/config-st3/Packages/Rust Enhanced/RustEnhanced.sublime-settings is also a bit weird, since Rust Enhanced seems to use my settings for eg. appearances, Cargo path.

lsp

rwols commented 4 years ago

This should be fixed for the ST3 version: https://github.com/sublimelsp/LSP/issues/372

Please try the following: Set log_debug, log_payloads and log_server to true in the settings, and then open the log panel with LSP: Toggle Log Panel in the command palette, and then restart the server with LSP: Restart Servers. (or: you may have to restart ST, I'm not sure anymore for the ST3 version).

Then, look for a request from your rls with the method client/registerCapability. Do these requests appear in the log?

rwols commented 4 years ago

LSP: rls: registering capability: didChangeWatchedFilesProvider

I don't see any other log line that registers documentRangeFormattingProvider, so, apparently rls doesn't register itself as that kind of provider.

rwols commented 4 years ago

You may have to play around with settings: https://github.com/rust-lang/rls#configuration

The server settings mentioned on that page map to this kind of structure in this client:

// LSP.sublime-settings
{
  "clients": {
    "rls": {
      // ...
      "settings": {
        "unstable_features": true
        // ...
      }
    }
  }
}

Restart ST3 for every such change.

detly commented 4 years ago

I applied these settings:

"settings":
{
    "LSP":
    {
        "rls":
        {
            "enabled": true,
            "settings": {
                "unstable_features": true
            }
        }
    }
}

I couldn't find a specific option on the RLS project page for range formatting though, and the remark for unstable_features says:

Currently no option requires this flag.

Restarting ST3 gives this line relating to capabilities:

:: <-- rls client/registerCapability(1): {'registrations': [{'id': 'rls-watch', 'method': 'workspace/didChangeWatchedFiles', 'registerOptions': {'watchers': [{'globPattern': '/home/jason/(path to project)/Cargo.lock'}, {'globPattern': '/home/jason/(path to project)/target', 'kind': 4}, {'globPattern': '/home/jason/(path to project)/Cargo.toml'}]}}]}
:: >>> rls 1: None

I actually tried to install RLS from the unstable channel, but rustup gave an error (which I did not copy at the time) which more or less said "not every package is available in unstable every day."

rwols commented 4 years ago

I don't know the exact kind of setting that would enable formatting. Perhaps @ehuss can be of help. You may also want to look into rust-analyzer as an alternative as that project has a lot of activity.

detly commented 4 years ago

Exactly the same symptom with rust-analyzer (nightly) - no format selection available. Log:

:: --> rust-analyzer initialize(1): {'rootUri': 'file:///home/jason/Code/(project path)', 'workspaceFolders': [{'uri': 'file:///home/jason/Code/(project path)', 'name': '(project path)'}], 'processId': 445842, 'clientInfo': {'version': '0.14.1', 'name': 'Sublime Text LSP'}, 'rootPath': '/home/jason/Code/(project path)', 'capabilities': {'textDocument': {'definition': {'dynamicRegistration': True, 'linkSupport': True}, 'declaration': {'dynamicRegistration': True, 'linkSupport': True}, 'references': {'dynamicRegistration': True}, 'typeDefinition': {'dynamicRegistration': True, 'linkSupport': True}, 'completion': {'completionItemKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]}, 'dynamicRegistration': True, 'completionItem': {'snippetSupport': True}}, 'documentSymbol': {'symbolKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]}, 'dynamicRegistration': True, 'hierarchicalDocumentSymbolSupport': True}, 'formatting': {'dynamicRegistration': True}, 'implementation': {'dynamicRegistration': True, 'linkSupport': True}, 'colorProvider': {'dynamicRegistration': True}, 'documentHighlight': {'dynamicRegistration': True}, 'rangeFormatting': {'dynamicRegistration': True}, 'publishDiagnostics': {'relatedInformation': True}, 'codeAction': {'dynamicRegistration': True, 'codeActionLiteralSupport': {'codeActionKind': {'valueSet': []}}}, 'signatureHelp': {'dynamicRegistration': True, 'signatureInformation': {'documentationFormat': ['markdown', 'plaintext'], 'parameterInformation': {'labelOffsetSupport': True}}}, 'hover': {'contentFormat': ['markdown', 'plaintext'], 'dynamicRegistration': True}, 'rename': {'dynamicRegistration': True}, 'synchronization': {'willSaveWaitUntil': True, 'dynamicRegistration': True, 'willSave': True, 'didSave': True}}, 'experimental': {}, 'workspace': {'workspaceEdit': {'documentChanges': True, 'failureHandling': 'abort'}, 'didChangeConfiguration': {'dynamicRegistration': True}, 'workspaceFolders': True, 'executeCommand': {}, 'applyEdit': True, 'symbol': {'symbolKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]}, 'dynamicRegistration': True}, 'configuration': True}, 'window': {'workDoneProgress': True, 'showMessage': {'messageActionItem': {'additionalPropertiesSupport': True}}}}, 'initializationOptions': {}}
:: --> rust-analyzer initialize(1): {'rootUri': 'file:///home/jason/Code/(project path)', 'workspaceFolders': [{'uri': 'file:///home/jason/Code/(project path)', 'name': '(project path)'}], 'processId': 445842, 'clientInfo': {'version': '0.14.1', 'name': 'Sublime Text LSP'}, 'rootPath': '/home/jason/Code/(project path)', 'capabilities': {'textDocument': {'definition': {'dynamicRegistration': True, 'linkSupport': True}, 'declaration': {'dynamicRegistration': True, 'linkSupport': True}, 'references': {'dynamicRegistration': True}, 'typeDefinition': {'dynamicRegistration': True, 'linkSupport': True}, 'completion': {'completionItemKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]}, 'dynamicRegistration': True, 'completionItem': {'snippetSupport': True}}, 'documentSymbol': {'symbolKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]}, 'dynamicRegistration': True, 'hierarchicalDocumentSymbolSupport': True}, 'formatting': {'dynamicRegistration': True}, 'implementation': {'dynamicRegistration': True, 'linkSupport': True}, 'colorProvider': {'dynamicRegistration': True}, 'documentHighlight': {'dynamicRegistration': True}, 'rangeFormatting': {'dynamicRegistration': True}, 'publishDiagnostics': {'relatedInformation': True}, 'codeAction': {'dynamicRegistration': True, 'codeActionLiteralSupport': {'codeActionKind': {'valueSet': []}}}, 'signatureHelp': {'dynamicRegistration': True, 'signatureInformation': {'documentationFormat': ['markdown', 'plaintext'], 'parameterInformation': {'labelOffsetSupport': True}}}, 'hover': {'contentFormat': ['markdown', 'plaintext'], 'dynamicRegistration': True}, 'rename': {'dynamicRegistration': True}, 'synchronization': {'willSaveWaitUntil': True, 'dynamicRegistration': True, 'willSave': True, 'didSave': True}}, 'experimental': {}, 'workspace': {'workspaceEdit': {'documentChanges': True, 'failureHandling': 'abort'}, 'didChangeConfiguration': {'dynamicRegistration': True}, 'workspaceFolders': True, 'executeCommand': {}, 'applyEdit': True, 'symbol': {'symbolKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]}, 'dynamicRegistration': True}, 'configuration': True}, 'window': {'workDoneProgress': True, 'showMessage': {'messageActionItem': {'additionalPropertiesSupport': True}}}}, 'initializationOptions': {}}
:: <<< rust-analyzer 1: {'capabilities': {'definitionProvider': True, 'referencesProvider': True, 'foldingRangeProvider': True, 'implementationProvider': True, 'workspaceSymbolProvider': True, 'experimental': {'joinLines': True, 'ssr': True, 'parentModule': True, 'runnables': {'kinds': ['cargo']}, 'onEnter': True}, 'codeLensProvider': {'resolveProvider': True}, 'selectionRangeProvider': True, 'semanticTokensProvider': {'legend': {'tokenTypes': ['comment', 'keyword', 'string', 'number', 'regexp', 'operator', 'namespace', 'type', 'struct', 'class', 'interface', 'enum', 'enumMember', 'typeParameter', 'function', 'member', 'property', 'macro', 'variable', 'parameter', 'attribute', 'boolean', 'builtinType', 'escapeSequence', 'formatSpecifier', 'generic', 'lifetime', 'punctuation', 'selfKeyword', 'typeAlias', 'union', 'unresolvedReference'], 'tokenModifiers': ['documentation', 'declaration', 'definition', 'static', 'abstract', 'deprecated', 'readonly', 'constant', 'controlFlow', 'injected', 'mutable', 'consuming', 'unsafe', 'attribute']}, 'full': {'delta': True}, 'range': True}, 'codeActionProvider': {'codeActionKinds': ['', 'quickfix', 'refactor', 'refactor.extract', 'refactor.inline', 'refactor.rewrite']}, 'callHierarchyProvider': True, 'hoverProvider': True, 'documentOnTypeFormattingProvider': {'firstTriggerCharacter': '=', 'moreTriggerCharacter': ['.', '>']}, 'signatureHelpProvider': {'triggerCharacters': ['(', ',']}, 'documentSymbolProvider': True, 'documentFormattingProvider': True, 'textDocumentSync': {'change': 2, 'openClose': True, 'save': {}}, 'documentHighlightProvider': True, 'typeDefinitionProvider': True, 'renameProvider': {'prepareProvider': True}, 'completionProvider': {'triggerCharacters': [':', '.']}}, 'serverInfo': {'version': '0d03fe6', 'name': 'rust-analyzer'}}
::  -> rust-analyzer initialized: {}
::  -> rust-analyzer textDocument/didOpen
:: <-- rust-analyzer client/registerCapability(0): {'registrations': [{'method': 'textDocument/didSave', 'id': 'textDocument/didSave', 'registerOptions': {'documentSelector': [{'pattern': '**/*.rs'}, {'pattern': '**/Cargo.toml'}, {'pattern': '**/Cargo.lock'}], 'includeText': False}}]}
:: >>> rust-analyzer 0: None
:: <-- rust-analyzer window/workDoneProgress/create(1): {'token': 'rustAnalyzer/roots scanned'}
:: >>> rust-analyzer 1: None
jwortmann commented 4 years ago

From 'documentFormattingProvider': True in the response to initialize you can see that rust-analyzer supports document formatting (seems to require rustfmt to be installed), but not range formatting, since there is no item documentRangeFormattingProvider listed and it isn't dynamically registered neither. Looks like there is a feature request for it at https://github.com/rust-analyzer/rust-analyzer/issues/5849 but it just isn't implemented yet.

rwols commented 3 years ago

I will close this as this seems to be an issue of language servers. You should join the discussion at https://github.com/rust-analyzer/rust-analyzer/issues/5849. Formatting the current selection is fully implemented in this client and works very well.