mirror of
https://github.com/microsoft/vscode-extension-samples.git
synced 2026-04-27 16:55:44 +08:00
Stream
This commit is contained in:
@ -1,10 +1,29 @@
|
||||
# LSP Example
|
||||
# LSP Example for Log Streaming
|
||||
|
||||
This is a repository adapted from [lsp-sample](https://github.com/Microsoft/vscode-extension-samples/tree/master/lsp-sample) to demonstrate
|
||||
|
||||
- Usage of the JSON output
|
||||
- Streaming the JSON into [LSP Inspector](https://github.com/Microsoft/language-server-protocol-inspector)
|
||||
|
||||
## Synopsis
|
||||
|
||||
- With `vscode-languageclient@5.1.0-next.9`, you can specify a JSON log output format with `[langId].trace.server` as follows:
|
||||
```json
|
||||
"languageServerExample.trace.server": {
|
||||
"format": "json",
|
||||
"verbosity": "verbose"
|
||||
}
|
||||
```
|
||||
- A [webview](https://github.com/Microsoft/language-server-protocol-inspector/tree/master/lsp-inspector-webview) build of the LSP Inspector can be downloaded here:
|
||||
- When using the Webview LSP Inspector, it will open a WebSocket Server taking incoming connection that sends logs following [this format](https://github.com/Microsoft/language-server-protocol-inspector#log-format).
|
||||
- You can stream the JSON log of any Language Server using `vscode-languageclient` to the LSP Inspector, and it will show a live view of the LSP connection.
|
||||
|
||||
|
||||
Heavily documented sample code for https://code.visualstudio.com/docs/extensions/example-language-server.
|
||||
|
||||
## Functionality
|
||||
|
||||
This Language Server works for plain text file. It has the following language features:
|
||||
|
||||
- Completions
|
||||
- Diagnostics regenerated on each file change or configuration change
|
||||
|
||||
@ -35,4 +54,4 @@ It also includes an End-to-End test.
|
||||
- If you want to debug the server as well use the launch configuration `Attach to Server`
|
||||
- In the [Extension Development Host] instance of VSCode, open a document in 'plain text' language mode.
|
||||
- Type `j` or `t` to see `Javascript` and `TypeScript` completion.
|
||||
- Enter text content such as `AAA aaa BBB`. The extension will emit diagnostics for all words in all-uppercase.
|
||||
- Enter text content such as `AAA aaa BBB`. The extension will emit diagnostics for all words in all-uppercase.
|
||||
|
||||
35
lsp-log-streaming-sample/client/package-lock.json
generated
35
lsp-log-streaming-sample/client/package-lock.json
generated
@ -4,6 +4,28 @@
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@types/events": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
|
||||
"integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "10.9.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.9.4.tgz",
|
||||
"integrity": "sha512-fCHV45gS+m3hH17zgkgADUSi2RR1Vht6wOZ0jyHP8rjiQra9f+mIcgwPQHllmDocYOstIEbKlxbFDYlgrTPYqw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/ws": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.0.tgz",
|
||||
"integrity": "sha512-i/dVaSjmTM92EFFFhmGL6AmHzvJ70XpAXmMLvNKh3JrRTGOiXvejfxe5+OSxcJK0paGOYHDaRLS8nXW6/FxSxg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/events": "1.2.0",
|
||||
"@types/node": "10.9.4"
|
||||
}
|
||||
},
|
||||
"ajv": {
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
|
||||
@ -101,6 +123,11 @@
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||
},
|
||||
"async-limiter": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
|
||||
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
@ -1801,6 +1828,14 @@
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"ws": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.0.0.tgz",
|
||||
"integrity": "sha512-c2UlYcAZp1VS8AORtpq6y4RJIkJ9dQz18W32SpR/qXGfLDZ2jU4y4wKvvZwqbi7U6gxFQTeE+urMbXU/tsDy4w==",
|
||||
"requires": {
|
||||
"async-limiter": "1.0.0"
|
||||
}
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
|
||||
|
||||
@ -18,6 +18,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode": "^1.1.21",
|
||||
"vscode-languageclient": "^5.1.0-next.9"
|
||||
"vscode-languageclient": "^5.1.0-next.9",
|
||||
"ws": "^6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ws": "^6.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,8 @@
|
||||
'use strict';
|
||||
|
||||
import * as path from 'path';
|
||||
import { workspace, ExtensionContext } from 'vscode';
|
||||
import { workspace, commands, ExtensionContext, OutputChannel } from 'vscode';
|
||||
import * as WebSocket from 'ws';
|
||||
|
||||
import {
|
||||
LanguageClient,
|
||||
@ -17,6 +18,14 @@ import {
|
||||
let client: LanguageClient;
|
||||
|
||||
export function activate(context: ExtensionContext) {
|
||||
const socketPort = workspace.getConfiguration('languageServerExample').get('port', 7000);
|
||||
let socket: WebSocket | null = null
|
||||
|
||||
commands.registerCommand('languageServerExample.startStreaming', () => {
|
||||
// Establish websocket connection
|
||||
socket = new WebSocket(`ws://localhost:${socketPort}`)
|
||||
})
|
||||
|
||||
// The server is implemented in node
|
||||
let serverModule = context.asAbsolutePath(
|
||||
path.join('server', 'out', 'server.js')
|
||||
@ -36,6 +45,29 @@ export function activate(context: ExtensionContext) {
|
||||
}
|
||||
};
|
||||
|
||||
// The log to send
|
||||
let log = ''
|
||||
const websocketOutputChannel: OutputChannel = {
|
||||
name: 'websocket',
|
||||
// Only append the logs but send them later
|
||||
append(value: string) {
|
||||
log += value
|
||||
console.log(value)
|
||||
},
|
||||
appendLine(value: string) {
|
||||
log += value
|
||||
// Don't send logs until WebSocket initialization
|
||||
if (socket && socket.readyState === WebSocket.OPEN) {
|
||||
socket.send(log)
|
||||
}
|
||||
log = ''
|
||||
},
|
||||
clear() {},
|
||||
show() {},
|
||||
hide() {},
|
||||
dispose() {}
|
||||
}
|
||||
|
||||
// Options to control the language client
|
||||
let clientOptions: LanguageClientOptions = {
|
||||
// Register the server for plain text documents
|
||||
@ -43,7 +75,9 @@ export function activate(context: ExtensionContext) {
|
||||
synchronize: {
|
||||
// Notify the server about file changes to '.clientrc files contained in the workspace
|
||||
fileEvents: workspace.createFileSystemWatcher('**/.clientrc')
|
||||
}
|
||||
},
|
||||
// Hijacks all LSP logs and redirect them to a specific port through WebSocket connection
|
||||
outputChannel: websocketOutputChannel
|
||||
};
|
||||
|
||||
// Create the language client and start the client.
|
||||
|
||||
@ -21,6 +21,12 @@
|
||||
],
|
||||
"main": "./client/out/extension",
|
||||
"contributes": {
|
||||
"commands": [
|
||||
{
|
||||
"command": "languageServerExample.startStreaming",
|
||||
"title": "Start Stream Logs into languageServerExample.port"
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
"type": "object",
|
||||
"title": "Example configuration",
|
||||
@ -31,6 +37,12 @@
|
||||
"default": 100,
|
||||
"description": "Controls the maximum number of problems produced by the server."
|
||||
},
|
||||
"languageServerExample.port": {
|
||||
"type": "number",
|
||||
"default": 7000,
|
||||
"scope": "window",
|
||||
"description": "The WebSocket port to stream LSP log data into."
|
||||
},
|
||||
"languageServerExample.trace.server": {
|
||||
"scope": "window",
|
||||
"type": "object",
|
||||
|
||||
Reference in New Issue
Block a user