From fd42e448ae9247e87dca72a416cafdea1e54d8cc Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Mon, 24 Sep 2018 19:35:46 -0500 Subject: [PATCH 1/3] vscode-dotty: upgrade dependencies --- vscode-dotty/package-lock.json | 46 +++++++++++++++++----------------- vscode-dotty/package.json | 4 +-- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/vscode-dotty/package-lock.json b/vscode-dotty/package-lock.json index 25d38e4e4a76..072bdcb9d223 100644 --- a/vscode-dotty/package-lock.json +++ b/vscode-dotty/package-lock.json @@ -11,9 +11,9 @@ "dev": true }, "@types/node": { - "version": "8.10.28", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.28.tgz", - "integrity": "sha512-iHsAzDg3OLH7JP+wipniUULHoDSWLgEDYOvsar6/mpAkTJd9/n23Ap8ikruMlvRTqMv/LXrflH9v/AfiEqaBGg==", + "version": "8.10.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.30.tgz", + "integrity": "sha512-Le8HGMI5gjFSBqcCuKP/wfHC19oURzkU2D+ERIescUoJd+CmNEMYBib9LQ4zj1HHEZOJQWhw2ZTnbD8weASh/Q==", "dev": true }, "ajv": { @@ -2068,41 +2068,41 @@ } }, "vscode-jsonrpc": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.6.2.tgz", - "integrity": "sha512-T24Jb5V48e4VgYliUXMnZ379ItbrXgOimweKaJshD84z+8q7ZOZjJan0MeDe+Ugb+uqERDVV8SBmemaGMSMugA==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz", + "integrity": "sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg==" }, "vscode-languageclient": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-5.0.1.tgz", - "integrity": "sha512-5o4mWbKRrjhgFPc3W1kXSWy9O2HQVacrgLI3gK98RsthKESnpgj9FX+7OQLtLgSvHhaqxJbVVz2xdPfeSDKaZg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-5.1.0.tgz", + "integrity": "sha512-Z95Kps8UqD4o17HE3uCkZuvenOsxHVH46dKmaGVpGixEFZigPaVuVxLM/JWeIY9aRenoC0ZD9CK1O7L4jpffKg==", "requires": { "semver": "^5.5.0", - "vscode-languageserver-protocol": "^3.10.3" + "vscode-languageserver-protocol": "3.13.0" } }, "vscode-languageserver": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-5.0.3.tgz", - "integrity": "sha512-itOImvZfDueQXMhy4pm2SwPKa3AShZvILXFcK/5X3ruiYdZozmx3OeD5Y92dVBt0OzTdbVD9MZcEelH4E7Eu3g==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-5.1.0.tgz", + "integrity": "sha512-CIsrgx2Y5VHS317g/HwkSTWYBIQmy0DwEyZPmB2pEpVOhYFwVsYpbiJwHIIyLQsQtmRaO4eA2xM8KPjNSdXpBw==", "requires": { - "vscode-languageserver-protocol": "^3.10.3", - "vscode-uri": "^1.0.5" + "vscode-languageserver-protocol": "3.13.0", + "vscode-uri": "^1.0.6" } }, "vscode-languageserver-protocol": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.12.0.tgz", - "integrity": "sha512-evY6hmyzLnwQrqlQWPrNBq1z8wrSNjLesmgPzeS6Zv11mVS5UJRel26hbM/DH5tHdn45huNzRW0eFHRmIm8LpA==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.13.0.tgz", + "integrity": "sha512-2ZGKwI+P2ovQll2PGAp+2UfJH+FK9eait86VBUdkPd9HRlm8e58aYT9pV/NYanHOcp3pL6x2yTLVCFMcTer0mg==", "requires": { - "vscode-jsonrpc": "^3.6.2", - "vscode-languageserver-types": "^3.12.0" + "vscode-jsonrpc": "^4.0.0", + "vscode-languageserver-types": "3.13.0" } }, "vscode-languageserver-types": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.12.0.tgz", - "integrity": "sha512-UxqnpzBToPO7Mi2tr/s5JeyPOSKSJtLB8lIdxCg9ZNdvP2cU8wS7iTDtwQKz91Ne4CUmTdf85ddR5SIZKXmMjQ==" + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.13.0.tgz", + "integrity": "sha512-BnJIxS+5+8UWiNKCP7W3g9FlE7fErFw0ofP5BXJe7c2tl0VeWh+nNHFbwAS2vmVC4a5kYxHBjRy0UeOtziemVA==" }, "vscode-uri": { "version": "1.0.6", diff --git a/vscode-dotty/package.json b/vscode-dotty/package.json index 09601ac80b2d..d5ea00d3a1ae 100644 --- a/vscode-dotty/package.json +++ b/vscode-dotty/package.json @@ -58,8 +58,8 @@ ], "dependencies": { "child-process-promise": "^2.2.1", - "vscode-languageclient": "^5.0.1", - "vscode-languageserver": "^5.0.3" + "vscode-languageclient": "^5.1.0", + "vscode-languageserver": "^5.1.0" }, "devDependencies": { "@types/mocha": "^5.2.5", From eb61770e92b0e6058abd409ed3cd934be14e81a7 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 25 Sep 2018 12:47:45 -0500 Subject: [PATCH 2/3] vscode-dotty: Use the same output channel for the client and server --- vscode-dotty/src/extension.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/vscode-dotty/src/extension.ts b/vscode-dotty/src/extension.ts index 52921936017a..c18ab58ab846 100644 --- a/vscode-dotty/src/extension.ts +++ b/vscode-dotty/src/extension.ts @@ -15,7 +15,7 @@ let outputChannel: vscode.OutputChannel export function activate(context: ExtensionContext) { extensionContext = context - outputChannel = vscode.window.createOutputChannel('Dotty Language Client'); + outputChannel = vscode.window.createOutputChannel("Dotty"); const sbtArtifact = "org.scala-sbt:sbt-launch:1.2.3" const buildSbtFile = `${vscode.workspace.rootPath}/build.sbt` @@ -158,12 +158,11 @@ function run(serverOptions: ServerOptions) { synchronize: { configurationSection: 'dotty' }, + outputChannel: outputChannel, revealOutputChannelOn: RevealOutputChannelOn.Never } - outputChannel.dispose() - - const client = new LanguageClient('dotty', 'Dotty Language Server', serverOptions, clientOptions); + const client = new LanguageClient("dotty", "Dotty", serverOptions, clientOptions) // Push the disposable to the context's subscriptions so that the // client can be deactivated on extension deactivation From ec8370f8d1cd8b52b64c8b45f173f8bfa4be6e43 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Mon, 24 Sep 2018 20:05:35 -0500 Subject: [PATCH 3/3] vscode-dotty: Fix hover functionality with old language server The current unreleased version of vscode-dotty depends on a new version of vscode-languageclient which parses hover messages in a stricter way, and Dotty Language Server <= 0.9.x sends incorrect hover messages due to a bug in lsp4j. The end result is that when using the current vscode-dotty on a project with an old version of dotty, the hover shows "[object Object]" instead of showing the type and documentation. This commit works around this by manually parsing the hover message when the server version is too old. --- vscode-dotty/package-lock.json | 11 ++++++++ vscode-dotty/package.json | 2 ++ vscode-dotty/src/compat.ts | 46 ++++++++++++++++++++++++++++++++++ vscode-dotty/src/extension.ts | 12 ++++++--- 4 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 vscode-dotty/src/compat.ts diff --git a/vscode-dotty/package-lock.json b/vscode-dotty/package-lock.json index 072bdcb9d223..fe381044e733 100644 --- a/vscode-dotty/package-lock.json +++ b/vscode-dotty/package-lock.json @@ -4,6 +4,12 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@types/compare-versions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/compare-versions/-/compare-versions-3.0.0.tgz", + "integrity": "sha512-HNXtUQQuW3ThO9DVfTNbdvClVr+8AZlNNa2pxk5qtEvObnT27qh0DdQXTN4h5PuTTGinxwXkRKXsllJxuAzGPw==", + "dev": true + }, "@types/mocha": { "version": "5.2.5", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.5.tgz", @@ -276,6 +282,11 @@ "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", "dev": true }, + "compare-versions": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.4.0.tgz", + "integrity": "sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", diff --git a/vscode-dotty/package.json b/vscode-dotty/package.json index d5ea00d3a1ae..1a08ad472c97 100644 --- a/vscode-dotty/package.json +++ b/vscode-dotty/package.json @@ -58,10 +58,12 @@ ], "dependencies": { "child-process-promise": "^2.2.1", + "compare-versions": "^3.4.0", "vscode-languageclient": "^5.1.0", "vscode-languageserver": "^5.1.0" }, "devDependencies": { + "@types/compare-versions": "^3.0.0", "@types/mocha": "^5.2.5", "@types/node": "^8.10.28", "typescript": "^2.9.2", diff --git a/vscode-dotty/src/compat.ts b/vscode-dotty/src/compat.ts new file mode 100644 index 000000000000..1d11e4236f24 --- /dev/null +++ b/vscode-dotty/src/compat.ts @@ -0,0 +1,46 @@ +import * as vscode from 'vscode'; + +import { HoverRequest } from 'vscode-languageclient'; +import { MarkedString, LanguageClient, LanguageClientOptions, RevealOutputChannelOn, + ServerOptions } from 'vscode-languageclient'; + +// Fix hover functionality when using this version of vscode-dotty with Dotty +// Language Server 0.9 or earlier. +// Without this, the displayed hover would be "[object Object]". +export function enableOldServerWorkaround(client: LanguageClient): void { + client.clientOptions.middleware = { + provideHover: (document, position, token, next) => { + // This code is adapted from HoverFeature#registerLanguageProvider in + // https://github.com/Microsoft/vscode-languageserver-node/blob/master/client/src/client.ts + return client + .sendRequest(HoverRequest.type, + client.code2ProtocolConverter.asTextDocumentPositionParams(document, position), token) + .then( + hover => { + if (!hover) { + return undefined + } + // The server is supposed to return string or { language: string, + // value: string } or an array of those things, but instead it returns + // an array of { value: string }. This used to work but with a recent + // vscode-languageclient the user ends up seeing "[object Object]" as + // the hover information. + // We work around this by manually parsing the array of { value: string } + // into a Hover. + const contents = hover.contents as { value: string }[] + let result: vscode.MarkdownString[] = [] + for (let element of contents) { + let item = new vscode.MarkdownString() + item.appendCodeblock(element.value, "scala") + result.push(item) + } + return new vscode.Hover(result) + }, + error => { + client.logFailedRequest(HoverRequest.type, error) + return Promise.resolve(null) + } + ) + } + } +} diff --git a/vscode-dotty/src/extension.ts b/vscode-dotty/src/extension.ts index c18ab58ab846..75e2accbbf64 100644 --- a/vscode-dotty/src/extension.ts +++ b/vscode-dotty/src/extension.ts @@ -4,11 +4,13 @@ import * as fs from 'fs'; import * as path from 'path'; import * as cpp from 'child-process-promise'; +import * as compareVersions from 'compare-versions'; import { ExtensionContext } from 'vscode'; import * as vscode from 'vscode'; import { LanguageClient, LanguageClientOptions, RevealOutputChannelOn, ServerOptions } from 'vscode-languageclient'; +import { enableOldServerWorkaround } from './compat' let extensionContext: ExtensionContext let outputChannel: vscode.OutputChannel @@ -36,7 +38,7 @@ export function activate(context: ExtensionContext) { run({ module: context.asAbsolutePath('out/src/passthrough-server.js'), args: [ port.toString() ] - }) + }, false) }) } else { @@ -72,11 +74,13 @@ function runLanguageServer(coursierPath: string, languageServerArtifactFile: str if (err) throw err else { const languageServerArtifact = data.toString().trim() + const languageServerVersion = languageServerArtifact.split(":")[2] + const isOldServer = compareVersions(languageServerVersion, "0.9.x") <= 0 fetchWithCoursier(coursierPath, languageServerArtifact).then((languageServerClasspath) => { run({ command: "java", args: ["-classpath", languageServerClasspath, "dotty.tools.languageserver.Main", "-stdio"] - }) + }, isOldServer) }) } }) @@ -149,7 +153,7 @@ function configureIDE(sbtClasspath: string, languageServerScalaVersion: string, }) } -function run(serverOptions: ServerOptions) { +function run(serverOptions: ServerOptions, isOldServer: boolean) { const clientOptions: LanguageClientOptions = { documentSelector: [ { language: 'scala', scheme: 'file', pattern: '**/*.scala' }, @@ -163,6 +167,8 @@ function run(serverOptions: ServerOptions) { } const client = new LanguageClient("dotty", "Dotty", serverOptions, clientOptions) + if (isOldServer) + enableOldServerWorkaround(client) // Push the disposable to the context's subscriptions so that the // client can be deactivated on extension deactivation