Skip to content

Progress reporting should respect client capabilities #4384

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

Closed
lnicola opened this issue May 9, 2020 · 4 comments · Fixed by #4403
Closed

Progress reporting should respect client capabilities #4384

lnicola opened this issue May 9, 2020 · 4 comments · Fixed by #4403

Comments

@lnicola
Copy link
Member

lnicola commented May 9, 2020

See https://microsoft.github.io/language-server-protocol/specifications/specification-current/#signalingWorkDoneProgressReporting, CC #144.

This affects Sublime, for example.

@rwols
Copy link

rwols commented May 9, 2020

We added support for server-initiated progress reporting in 0.10.1.

However, it looks like rust-analyzer doesn't request window/workDoneProgress/create first.
It should do this request to let an editor prepare itself for more progress (we simply store the provided token in a dict).

The general flow of messages should look like this:

server -> editor request window/workDoneProgress/create
server -> editor notification $/progress with begin kind
zero or more server -> editor notifications $/progress with report kind
server -> editor notification $/progress with end kind.

The end kind is important because we release memory associated with the progress reporting token.

@golddranks
Copy link

I have been testing this a bit, and when setting the project folder properly, it seems to initiate the progress correctly:

:: --> rust-analyzer initialize(1): {'initializationOptions': {}, 'capabilities': {'window': {'workDoneProgress': True}, 'workspace': {'configuration': 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}, 'executeCommand': {}, 'applyEdit': True, 'workspaceFolders': True, 'workspaceEdit': {'failureHandling': 'abort', 'documentChanges': True}, 'didChangeConfiguration': {'dynamicRegistration': True}}, 'experimental': {}, 'textDocument': {'completion': {'completionItem': {'snippetSupport': True}, 'dynamicRegistration': True, '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]}}, 'synchronization': {'willSaveWaitUntil': True, 'willSave': True, 'dynamicRegistration': True, 'didSave': True}, 'signatureHelp': {'signatureInformation': {'parameterInformation': {'labelOffsetSupport': True}, 'documentationFormat': ['markdown', 'plaintext']}, 'dynamicRegistration': 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}, 'declaration': {'linkSupport': True, 'dynamicRegistration': True}, 'rangeFormatting': {'dynamicRegistration': True}, 'codeAction': {'codeActionLiteralSupport': {'codeActionKind': {'valueSet': []}}, 'dynamicRegistration': True}, 'formatting': {'dynamicRegistration': True}, 'hover': {'dynamicRegistration': True, 'contentFormat': ['markdown', 'plaintext']}, 'implementation': {'linkSupport': True, 'dynamicRegistration': True}, 'references': {'dynamicRegistration': True}, 'definition': {'linkSupport': True, 'dynamicRegistration': True}, 'typeDefinition': {'linkSupport': True, 'dynamicRegistration': True}, 'publishDiagnostics': {'relatedInformation': True}, 'documentHighlight': {'dynamicRegistration': True}, 'colorProvider': {'dynamicRegistration': True}, 'rename': {'dynamicRegistration': True}}}, 'rootPath': '/Users/kon/adhoc/analyzer_test/test1', 'clientInfo': {'name': 'Sublime Text LSP', 'version': '0.10.1'}, 'workspaceFolders': [{'name': 'test1', 'uri': 'file:///Users/kon/adhoc/analyzer_test/test1'}], 'processId': 27997, 'rootUri': 'file:///Users/kon/adhoc/analyzer_test/test1'}
:: <<< rust-analyzer 1: {'capabilities': {'selectionRangeProvider': True, 'callHierarchyProvider': True, 'completionProvider': {'triggerCharacters': [':', '.']}, 'codeLensProvider': {'resolveProvider': True}, 'renameProvider': {'prepareProvider': True}, 'documentSymbolProvider': True, 'implementationProvider': True, 'typeDefinitionProvider': True, 'definitionProvider': True, 'codeActionProvider': {'codeActionKinds': ['', 'quickfix', 'refactor', 'refactor.extract', 'refactor.inline', 'refactor.rewrite', 'source', 'source.organizeImports']}, 'documentHighlightProvider': True, 'signatureHelpProvider': {'triggerCharacters': ['(', ',']}, 'semanticTokensProvider': {'documentProvider': True, 'legend': {'tokenModifiers': ['documentation', 'declaration', 'definition', 'static', 'abstract', 'deprecated', 'readonly', 'constant', 'controlFlow', 'mutable', 'unsafe'], 'tokenTypes': ['comment', 'keyword', 'string', 'number', 'regexp', 'operator', 'namespace', 'type', 'struct', 'class', 'interface', 'enum', 'typeParameter', 'function', 'member', 'property', 'macro', 'variable', 'parameter', 'label', 'attribute', 'builtinType', 'enumMember', 'lifetime', 'typeAlias', 'union', 'unresolvedReference', 'formatSpecifier']}, 'rangeProvider': True}, 'documentOnTypeFormattingProvider': {'moreTriggerCharacter': ['.', '>'], 'firstTriggerCharacter': '='}, 'workspaceSymbolProvider': True, 'documentFormattingProvider': True, 'textDocumentSync': {'openClose': True, 'save': {}, 'change': 2}, 'foldingRangeProvider': True, 'hoverProvider': True, 'referencesProvider': True}}
::  -> rust-analyzer initialized: {}
::  -> rust-analyzer textDocument/didOpen
::  -> rust-analyzer textDocument/didOpen
:: <-- rust-analyzer window/workDoneProgress/create(1): {'token': 'rustAnalyzer/startup'}
:: >>> rust-analyzer 1: None
:: <-  rust-analyzer $/progress: {'token': 'rustAnalyzer/startup', 'value': {'title': 'rust-analyzer', 'kind': 'begin', 'message': '0/10 packages', 'percentage': 0.0}}
:: <-  rust-analyzer $/progress: {'token': 'rustAnalyzer/cargoWatcher', 'value': {'kind': 'end'}}
:: <-  rust-analyzer $/progress: {'token': 'rustAnalyzer/startup', 'value': {'kind': 'report', 'message': '1/10 packages', 'percentage': 10.0}}
:: <-  rust-analyzer $/progress: {'token': 'rustAnalyzer/startup', 'value': {'kind': 'report', 'message': '2/10 packages', 'percentage': 20.0}}
:: <-  rust-analyzer $/progress: {'token': 'rustAnalyzer/startup', 'value': {'kind': 'report', 'message': '3/10 packages', 'percentage': 30.0}}
:: <-  rust-analyzer $/progress: {'token': 'rustAnalyzer/startup', 'value': {'kind': 'report', 'message': '4/10 packages', 'percentage': 40.0}}

On the other hand, when opening a single file that doesn't belong to a project ("workspaceFolders": null), it emits invalid LSP, not creating the progress token properly:

:: --> rust-analyzer initialize(1): {'workspaceFolders': None, 'rootPath': None, 'capabilities': {'textDocument': {'declaration': {'dynamicRegistration': True, 'linkSupport': True}, 'implementation': {'dynamicRegistration': True, 'linkSupport': True}, 'completion': {'dynamicRegistration': True, '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]}, 'completionItem': {'snippetSupport': True}}, 'synchronization': {'dynamicRegistration': True, 'willSave': True, 'didSave': True, 'willSaveWaitUntil': True}, 'formatting': {'dynamicRegistration': True}, 'references': {'dynamicRegistration': True}, 'colorProvider': {'dynamicRegistration': True}, 'rangeFormatting': {'dynamicRegistration': True}, 'publishDiagnostics': {'relatedInformation': True}, 'documentSymbol': {'dynamicRegistration': True, '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]}}, 'rename': {'dynamicRegistration': True}, 'codeAction': {'dynamicRegistration': True, 'codeActionLiteralSupport': {'codeActionKind': {'valueSet': []}}}, 'signatureHelp': {'dynamicRegistration': True, 'signatureInformation': {'documentationFormat': ['markdown', 'plaintext'], 'parameterInformation': {'labelOffsetSupport': True}}}, 'typeDefinition': {'dynamicRegistration': True, 'linkSupport': True}, 'documentHighlight': {'dynamicRegistration': True}, 'hover': {'dynamicRegistration': True, 'contentFormat': ['markdown', 'plaintext']}, 'definition': {'dynamicRegistration': True, 'linkSupport': True}}, 'experimental': {}, 'workspace': {'workspaceFolders': True, 'didChangeConfiguration': {'dynamicRegistration': True}, 'workspaceEdit': {'failureHandling': 'abort', 'documentChanges': True}, 'configuration': True, 'executeCommand': {}, 'symbol': {'dynamicRegistration': True, '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]}}, 'applyEdit': True}, 'window': {'workDoneProgress': True}}, 'initializationOptions': {}, 'processId': 95939, 'clientInfo': {'version': '0.10.1', 'name': 'Sublime Text LSP'}, 'rootUri': None}
:: <<< rust-analyzer 1: {'capabilities': {'documentHighlightProvider': True, 'selectionRangeProvider': True, 'documentOnTypeFormattingProvider': {'firstTriggerCharacter': '=', 'moreTriggerCharacter': ['.', '>']}, 'referencesProvider': True, 'completionProvider': {'triggerCharacters': [':', '.']}, 'documentSymbolProvider': True, 'hoverProvider': True, 'textDocumentSync': {'change': 2, 'save': {}, 'openClose': True}, 'codeLensProvider': {'resolveProvider': True}, 'renameProvider': {'prepareProvider': True}, 'semanticTokensProvider': {'legend': {'tokenTypes': ['comment', 'keyword', 'string', 'number', 'regexp', 'operator', 'namespace', 'type', 'struct', 'class', 'interface', 'enum', 'typeParameter', 'function', 'member', 'property', 'macro', 'variable', 'parameter', 'label', 'attribute', 'builtinType', 'enumMember', 'lifetime', 'typeAlias', 'union', 'unresolvedReference', 'formatSpecifier'], 'tokenModifiers': ['documentation', 'declaration', 'definition', 'static', 'abstract', 'deprecated', 'readonly', 'constant', 'controlFlow', 'mutable', 'unsafe']}, 'rangeProvider': True, 'documentProvider': True}, 'codeActionProvider': {'codeActionKinds': ['', 'quickfix', 'refactor', 'refactor.extract', 'refactor.inline', 'refactor.rewrite', 'source', 'source.organizeImports']}, 'implementationProvider': True, 'workspaceSymbolProvider': True, 'callHierarchyProvider': True, 'definitionProvider': True, 'foldingRangeProvider': True, 'documentFormattingProvider': True, 'typeDefinitionProvider': True, 'signatureHelpProvider': {'triggerCharacters': ['(', ',']}}}
::  -> rust-analyzer initialized: {}
::  -> rust-analyzer textDocument/didOpen
:: <-  rust-analyzer window/showMessage: {'message': 'rust-analyzer failed to discover workspace, no Cargo.toml found, dirs searched: /Applications/Sublime Text.app/Contents/MacOS', 'type': 1}
:: <-  rust-analyzer $/progress: {'value': {'message': 'rust-analyzer loaded, 1 packages', 'kind': 'end'}, 'token': 'rustAnalyzer/startup'}

@rwols
Copy link

rwols commented May 9, 2020

Looks good when there are workspaceFolders. I do see this lonely progress notification:

:: <-  rust-analyzer $/progress: {'token': 'rustAnalyzer/cargoWatcher', 'value': {'kind': 'end'}}

kjeremy added a commit to kjeremy/rust-analyzer that referenced this issue May 9, 2020
bors bot added a commit that referenced this issue May 11, 2020
4403: Check client capabilities before sending progress notifications r=kjeremy a=kjeremy

Fixes #4384

Co-authored-by: Jeremy Kolb <[email protected]>
@bors bors bot closed this as completed in d4471dc May 11, 2020
@gwutz
Copy link
Contributor

gwutz commented May 17, 2020

I wonder if every progress should initiate the window/workDoneProgress/create
The cargoWatcher should initiate his progress too right? So i can create 2 progressbars for each action.

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

Successfully merging a pull request may close this issue.

4 participants