support streaming in language feature providers (Observable returns)
Created by: sqs
Sourcegraph extensions can now return Observables from provideHover
, provideReferences
, and other language feature provider methods.
This is useful for:
- Streaming references, especially for external references, which take a lot longer than local references.
- Streaming hovers while the workspace is initializing, so the user doesn't need to keep moving their mouse around on tokens to see if it's ready yet.
Demo videos:
- https://slack-files.com/T02FSM7DL-FE6RZTVJ6-24bbd82b96
- https://slack-files.com/T02FSM7DL-FE6MR49JQ-6169e33377
Example code:
import * as sourcegraph from 'sourcegraph'
import { interval } from 'rxjs'
import { map, bufferCount } from 'rxjs/operators'
export function activate(): void {
// Normal (non-streaming) provider
sourcegraph.languages.registerHoverProvider(['*'], {
provideHover: () => ({
contents: { value: ' Hello from an extension!' },
}),
})
// "Streaming" hover provider
sourcegraph.languages.registerHoverProvider(['*'], {
provideHover: () =>
interval(100).pipe(
map(n => ({
contents: { kind: sourcegraph.MarkupKind.Markdown, value: `Counter: ${n}` },
}))
),
})
// "Streaming" references provider
sourcegraph.languages.registerReferenceProvider(['*'], {
provideReferences: doc =>
interval(500).pipe(
bufferCount(7),
map(values => {
const lines = doc.text.split('\n')
const lineNumbers = values.map(value => (value * 7) % lines.length)
return lineNumbers.filter(line => lines[line].length > 3).map(
line =>
({
uri: new sourcegraph.URI(doc.uri),
range: new sourcegraph.Range(
line,
lines[line].length / 3,
line,
(lines[line].length * 2) / 3
),
} as sourcegraph.Location)
)
})
),
})
}
TODOs (post-merge):
- Further cleanup in the jsonrpc2 TS directory. We are no longer using standard JSON-RPC 2.0, so we should remove other JSON-RPC 2.0 features we don't use and update docs.