diff --git a/lsp-multi-server-sample/.gitignore b/lsp-multi-server-sample/.gitignore new file mode 100644 index 00000000..4228f913 --- /dev/null +++ b/lsp-multi-server-sample/.gitignore @@ -0,0 +1,3 @@ +out +node_modules +client/server \ No newline at end of file diff --git a/lsp-multi-server-sample/.vscode/launch.json b/lsp-multi-server-sample/.vscode/launch.json new file mode 100644 index 00000000..8658dad9 --- /dev/null +++ b/lsp-multi-server-sample/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + "version": "0.2.0", + // List of configurations. Add new configurations or edit existing ones. + "configurations": [ + { + "name": "Launch Client", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": ["--extensionDevelopmentPath=${workspaceRoot}/client" ], + "stopOnEntry": false, + "sourceMaps": true, + "outFiles": [ "${workspaceRoot}/client/out/src/**/*.js" ], + "preLaunchTask": "Client Watch" + }, + { + "name": "Attach to Server", + "type": "node", + "request": "attach", + "port": 6010, + "sourceMaps": true, + "outFiles": [ "${workspaceRoot}/client/server/**/*.js" ], + "preLaunchTask": "Server Watch" + } + ] +} diff --git a/lsp-multi-server-sample/.vscode/settings.json b/lsp-multi-server-sample/.vscode/settings.json new file mode 100644 index 00000000..ed5b51ff --- /dev/null +++ b/lsp-multi-server-sample/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "files.exclude": { + "out": false // set this to true to hide the "out" folder with the compiled JS files + }, + "search.exclude": { + "out": true // set this to false to include "out" folder in search results + }, + "typescript.tsdk": "./node_modules/typescript/lib" +} \ No newline at end of file diff --git a/lsp-multi-server-sample/.vscode/tasks.json b/lsp-multi-server-sample/.vscode/tasks.json new file mode 100644 index 00000000..c3bccf46 --- /dev/null +++ b/lsp-multi-server-sample/.vscode/tasks.json @@ -0,0 +1,80 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "taskName": "Compile", + "dependsOn": [ + "Client Compile", + "Server Compile" + ], + "problemMatcher": [] + }, + { + "taskName": "Client Compile", + "type": "shell", + "command": "npm run client-compile", + "group": "build", + "presentation": { + "panel": "dedicated", + "reveal": "never" + + }, + "problemMatcher": [ + "$tsc" + ] + }, + { + "taskName": "Server Compile", + "type": "shell", + "command": "npm run server-compile", + "group": "build", + "presentation": { + "panel": "dedicated", + "reveal": "never" + }, + "problemMatcher": [ + "$tsc" + ] + }, + { + "taskName": "Watch", + "dependsOn": [ + "Client Watch", + "Server Watch" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": [] + }, + { + "taskName": "Client Watch", + "type": "shell", + "command": "npm run client-watch", + "isBackground": true, + "group": "build", + "presentation": { + "panel": "dedicated", + "reveal": "never" + }, + "problemMatcher": [ + "$tsc-watch" + ] + }, + { + "taskName": "Server Watch", + "type": "shell", + "command": "npm run server-watch", + "isBackground": true, + "group": "build", + "presentation": { + "panel": "dedicated", + "reveal": "never" + }, + "problemMatcher": [ + "$tsc-watch" + ] + } + ] +} \ No newline at end of file diff --git a/lsp-multi-server-sample/License.txt b/lsp-multi-server-sample/License.txt new file mode 100644 index 00000000..dcdd1210 --- /dev/null +++ b/lsp-multi-server-sample/License.txt @@ -0,0 +1,17 @@ +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files +(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lsp-multi-server-sample/README.md b/lsp-multi-server-sample/README.md new file mode 100644 index 00000000..1ff16c23 --- /dev/null +++ b/lsp-multi-server-sample/README.md @@ -0,0 +1,16 @@ +# LSP Multi Server Example + +A language server example that demonstrates how to start a server per workspace folder. If the workspace has nested workspace folders only a server for the outer most workspace folder is started assuming that the language service handles nested code. + +The example uses proposed Language Server protocol. So the code demoed here might change when the final version of the configuration and workspace folder protocol is released. + +## Compile and Run + +- run `npm install` in this folder. This installs all necessary npm modules in both the client and server folder +- open VS Code on this folder. +- Press Ctrl+Shift+B to compile the client and server +- Switch to the Debug viewlet +- Select `Launch Client` from the drop down +- Run the lauch config +- If you want to debug the server as well use the launch configuration `Attach to Server` + diff --git a/lsp-multi-server-sample/client/.vscodeignore b/lsp-multi-server-sample/client/.vscodeignore new file mode 100644 index 00000000..9ca85fe6 --- /dev/null +++ b/lsp-multi-server-sample/client/.vscodeignore @@ -0,0 +1,7 @@ +.vscode/** +typings/** +**/*.ts +**/*.map +.gitignore +tsconfig.json +vsc-extension-quickstart.md diff --git a/multi-lsp-sample/client/extension.ts b/lsp-multi-server-sample/client/extension.ts similarity index 76% rename from multi-lsp-sample/client/extension.ts rename to lsp-multi-server-sample/client/extension.ts index 55806828..4a285d2d 100644 --- a/multi-lsp-sample/client/extension.ts +++ b/lsp-multi-server-sample/client/extension.ts @@ -1,6 +1,6 @@ import * as path from 'path'; import { - workspace as Workspace, window as Window, ExtensionContext, TextDocument, OutputChannel + workspace as Workspace, window as Window, ExtensionContext, TextDocument, OutputChannel, WorkspaceFolder } from 'vscode'; import { @@ -10,11 +10,19 @@ import { let defaultClient: LanguageClient; let clients: Map = new Map(); +function getOuterMostWorkspaceFolder(folder: WorkspaceFolder): WorkspaceFolder { + let result = folder; + let candidate: WorkspaceFolder; + while((candidate = Workspace.getWorkspaceFolder(folder.uri)) !== void 0) { + result = candidate; + } + return result; +} + export function activate(_context: ExtensionContext) { - let module = path.join(__dirname, '..', 'server', 'server.js'); - let outputChannel: OutputChannel = Window.createOutputChannel('Multi-LSP-Example'); + let outputChannel: OutputChannel = Window.createOutputChannel('lsp-multi-server-example'); function didOpenTextDocument(document: TextDocument): void { // We are only interested in language mode text @@ -34,13 +42,10 @@ export function activate(_context: ExtensionContext) { documentSelector: [ { scheme: 'untitled', language: 'plaintext' } ], - synchronize: { - configurationSection: 'multi-lsp' - }, diagnosticCollectionName: 'multi-lsp', outputChannel: outputChannel } - defaultClient = new LanguageClient('multi-lsp', 'Multi-LSP', serverOptions, clientOptions); + defaultClient = new LanguageClient('lsp-multi-server-example', 'LSP Multi Server Example', serverOptions, clientOptions); defaultClient.registerFeatures(ProposedProtocol(defaultClient)); defaultClient.start(); return; @@ -51,6 +56,9 @@ export function activate(_context: ExtensionContext) { if (!folder) { return; } + // If we have nested workspace folders we only start a server on the outer most workspace folder. + folder = getOuterMostWorkspaceFolder(folder); + if (!clients.has(folder.uri.toString())) { let debugOptions = { execArgv: ["--nolazy", `--inspect=${6011 + clients.size}`] }; let serverOptions = { @@ -61,18 +69,14 @@ export function activate(_context: ExtensionContext) { documentSelector: [ { scheme: 'file', language: 'plaintext', pattern: `${folder.uri.fsPath}/**/*` } ], - synchronize: { - configurationSection: 'multi-lsp' - }, - diagnosticCollectionName: 'multi-lsp', + diagnosticCollectionName: 'lsp-multi-server-example', workspaceFolder: folder, outputChannel: outputChannel } - let client = new LanguageClient('multi-lsp', 'Multi-LSP', serverOptions, clientOptions); + let client = new LanguageClient('lsp-multi-server-example', 'LSP Multi Server Example', serverOptions, clientOptions); client.registerFeatures(ProposedProtocol(client)); client.start(); clients.set(folder.uri.toString(), client); - } } diff --git a/multi-lsp-sample/client/package.json b/lsp-multi-server-sample/client/package.json similarity index 60% rename from multi-lsp-sample/client/package.json rename to lsp-multi-server-sample/client/package.json index e2f9d897..d09ebe3a 100644 --- a/multi-lsp-sample/client/package.json +++ b/lsp-multi-server-sample/client/package.json @@ -1,6 +1,6 @@ { - "name": "multi-lsp", - "description": "Example showing multiple LSP servers running", + "name": "lsp-multi-server-example-client-part", + "description": "A language server example demoing servers per workspace folder", "version": "0.0.1", "publisher": "vscode", "engines": { @@ -14,13 +14,13 @@ "type": "object", "title": "Multi LSP configuration", "properties": { - "multi-lsp.enable": { + "lsp-multi-server-example.enable": { "scope": "resource", "type": "boolean", "default": true, "description": "Controls the enablement." }, - "multi-lsp.options": { + "lsp-multi-server-example.options": { "scope": "resource", "type": "object", "default": {}, @@ -31,16 +31,14 @@ }, "main": "./out/extension", "scripts": { - "vscode:prepublish": "node ./node_modules/vscode/bin/compile", - "watch": "tsc -watch -p ./", - "update-vscode": "node ./node_modules/vscode/bin/install" - }, - "devDependencies": { - "vscode": "^1.1.5", - "typescript": "^2.4.2", - "@types/node": "^6.0.87" + "vscode:prepublish": "tsc -p ./", + "compile": "tsc -p ./", + "watch": "tsc -w -p ./", + "update-vscode": "node ./node_modules/vscode/bin/install", + "postinstall": "node ./node_modules/vscode/bin/install" }, "dependencies": { + "vscode": "^1.1.5", "vscode-languageclient": "next" } } \ No newline at end of file diff --git a/lsp-multi-server-sample/client/tsconfig.json b/lsp-multi-server-sample/client/tsconfig.json new file mode 100644 index 00000000..63d77358 --- /dev/null +++ b/lsp-multi-server-sample/client/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "module": "commonjs", + "target": "es6", + "outDir": "out", + "lib": [ "es6"], + "sourceMap": true + }, + "exclude": [ + "node_modules", + "server" + ] +} \ No newline at end of file diff --git a/lsp-multi-server-sample/package.json b/lsp-multi-server-sample/package.json new file mode 100644 index 00000000..11080a21 --- /dev/null +++ b/lsp-multi-server-sample/package.json @@ -0,0 +1,25 @@ +{ + "name": "lsp-mulit-server-sample", + "description": "A language server example demoing servers per workspace folder", + "author": "Microsoft Corporation", + "license": "MIT", + "version": "0.0.1", + "publisher": "vscode", + "repository": { + "type": "git", + "url": "https://github.com/Microsoft/vscode-extension-samples" + }, + "scripts": { + "postinstall": "cd server && npm install && cd ../client && npm install && cd ..", + "compile": "tsc -p client/tsconfig.json && cd server && npm run installServer && cd .. && tsc -p server/tsconfig.json", + "client-compile": "tsc -p client/tsconfig.json", + "client-watch": "tsc -w -p client/tsconfig.json", + "server-compile": "cd server && npm run installServer && cd .. && tsc -p server/tsconfig.json", + "server-watch": "cd server && npm run installServer && cd .. && tsc -w -p server/tsconfig.json" + }, + "devDependencies": { + "@types/mocha": "^2.2.42", + "@types/node": "^6.0.88", + "typescript": "^2.5.2" + } +} \ No newline at end of file diff --git a/lsp-multi-server-sample/server/package.json b/lsp-multi-server-sample/server/package.json new file mode 100644 index 00000000..47b3c0dc --- /dev/null +++ b/lsp-multi-server-sample/server/package.json @@ -0,0 +1,21 @@ +{ + "name": "lsp-multi-server-example-server-part", + "description": "A language server example demoing servers per workspace folder", + "version": "0.0.1", + "license": "MIT", + "engines": { + "node": "*" + }, + "repository": { + "type": "git", + "url": "https://github.com/Microsoft/vscode-extension-samples" + }, + "dependencies": { + "vscode-languageserver": "next" + }, + "scripts": { + "installServer": "installServerIntoExtension ../client ./package.json ./tsconfig.json", + "compile": "installServerIntoExtension ../client ./package.json ./tsconfig.json && tsc -p .", + "watch": "installServerIntoExtension ../client ./package.json ./tsconfig.json && tsc -w -p ." + } +} \ No newline at end of file diff --git a/multi-lsp-sample/server/src/server.ts b/lsp-multi-server-sample/server/src/server.ts similarity index 100% rename from multi-lsp-sample/server/src/server.ts rename to lsp-multi-server-sample/server/src/server.ts diff --git a/multi-lsp-sample/server/src/tsconfig.json b/lsp-multi-server-sample/server/src/tsconfig.json similarity index 100% rename from multi-lsp-sample/server/src/tsconfig.json rename to lsp-multi-server-sample/server/src/tsconfig.json diff --git a/lsp-multi-server-sample/server/tsconfig.json b/lsp-multi-server-sample/server/tsconfig.json new file mode 100644 index 00000000..6032b82b --- /dev/null +++ b/lsp-multi-server-sample/server/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es6", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "lib" : [ "es2016" ], + "outDir": "../client/server" + }, + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/multi-lsp-sample/client/.vscode/launch.json b/multi-lsp-sample/client/.vscode/launch.json deleted file mode 100644 index 82f0b92d..00000000 --- a/multi-lsp-sample/client/.vscode/launch.json +++ /dev/null @@ -1,17 +0,0 @@ -// A launch configuration that compiles the extension and then opens it inside a new window -{ - "version": "0.1.0", - "configurations": [ - { - "name": "Launch Extension", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], - "stopOnEntry": false, - "sourceMaps": true, - "outFiles": ["${workspaceRoot}/out/**/*.js"], - "preLaunchTask": "npm: watch" - } - ] -} \ No newline at end of file diff --git a/multi-lsp-sample/client/.vscode/settings.json b/multi-lsp-sample/client/.vscode/settings.json deleted file mode 100644 index 3734074a..00000000 --- a/multi-lsp-sample/client/.vscode/settings.json +++ /dev/null @@ -1,13 +0,0 @@ -// Place your settings in this file to overwrite default and user settings. -{ - "files.exclude": { - "out": false // set this to true to hide the "out" folder with the compiled JS files - }, - "search.exclude": { - "out": true - }, - "editor.insertSpaces": false, - "editor.tabSize": 4, - "typescript.tsdk": "./node_modules/typescript/lib", "testbed.trace.server": "verbose" - , "testbed.server.trace": "verbose" -} \ No newline at end of file diff --git a/multi-lsp-sample/client/.vscode/tasks.json b/multi-lsp-sample/client/.vscode/tasks.json deleted file mode 100644 index 8562f02a..00000000 --- a/multi-lsp-sample/client/.vscode/tasks.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "watch", - "isBackground": true, - "problemMatcher": [ - "$tsc-watch" - ], - "group": { - "kind": "build", - "isDefault": true - } - } - ] -} \ No newline at end of file diff --git a/multi-lsp-sample/server/.vscode/launch.json b/multi-lsp-sample/server/.vscode/launch.json deleted file mode 100644 index 204d763d..00000000 --- a/multi-lsp-sample/server/.vscode/launch.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "version": "0.1.0", - // List of configurations. Add new configurations or edit existing ones. - "configurations": [ - { - "name": "Attach", - "type": "node", - "request": "attach", - // TCP/IP address. Default is "localhost". - "address": "localhost", - // Port to attach to. - "port": 6012, - "protocol": "inspector", - "sourceMaps": false, - "outDir": "${workspaceRoot}/../testbed/server" - } - ] -} \ No newline at end of file diff --git a/multi-lsp-sample/server/.vscode/settings.json b/multi-lsp-sample/server/.vscode/settings.json deleted file mode 100644 index 76145fca..00000000 --- a/multi-lsp-sample/server/.vscode/settings.json +++ /dev/null @@ -1,8 +0,0 @@ -// Place your settings in this file to overwrite default and user settings. -{ - "javascript.validate.enable": false, - "files.trimTrailingWhitespace": true, - "editor.insertSpaces": false, - "editor.tabSize": 4, - "typescript.tsdk": "./node_modules/typescript/lib" -} \ No newline at end of file diff --git a/multi-lsp-sample/server/.vscode/tasks.json b/multi-lsp-sample/server/.vscode/tasks.json deleted file mode 100644 index 13f1bf14..00000000 --- a/multi-lsp-sample/server/.vscode/tasks.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "watch", - "isBackground": true, - "problemMatcher": [ - "$tsc-watch" - ], - "group": { - "kind": "build", - "isDefault": true - } - } - ] -} \ No newline at end of file diff --git a/multi-lsp-sample/server/package.json b/multi-lsp-sample/server/package.json deleted file mode 100644 index 703ea029..00000000 --- a/multi-lsp-sample/server/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "multi-lsp-server", - "version": "0.1.0", - "description": "Multi server example", - "engines": { - "node": "*" - }, - "private": true, - "main": "./lib/server.js", - "dependencies": { - "vscode-languageserver": "next" - }, - "devDependencies": { - "typescript": "^2.4.2", - "@types/node": "^6.0.87" - }, - "scripts": { - "compile": "installServerIntoExtension ../client ./package.json ./src/tsconfig.json && tsc -p ./src", - "watch": "installServerIntoExtension ../client ./package.json ./src/tsconfig.json && tsc --watch -p ./src" - } -} \ No newline at end of file