Skip to content

Commit

Permalink
Refactor worksheet support, make it a dynamic feature
Browse files Browse the repository at this point in the history
- Only enable worksheet features on the client if the server supports
them using the LSP support for dynamic feature registration.
- Replace the global functions and state in worksheet.ts by a
WorksheetProvider class, move some of the global functions specific to
one worksheet into Worksheet
  • Loading branch information
smarter committed Oct 10, 2018
1 parent 214d1fe commit 0f465e5
Show file tree
Hide file tree
Showing 5 changed files with 324 additions and 281 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ class DottyLanguageServer extends LanguageServer
rootUri = params.getRootUri
assert(rootUri != null)

val c = new ServerCapabilities
class DottyServerCapabilities(val worksheetRunProvider: Boolean = true) extends lsp4j.ServerCapabilities

val c = new DottyServerCapabilities
c.setTextDocumentSync(TextDocumentSyncKind.Full)
c.setDocumentHighlightProvider(true)
c.setDocumentSymbolProvider(true)
Expand Down
6 changes: 4 additions & 2 deletions vscode-dotty/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@
"commands": [
{
"command": "worksheet.evaluate",
"title": "Run worksheet"
"title": "Run worksheet",
"category": "Scala"
},
{
"command": "worksheet.cancel",
"title": "Cancel worksheet evaluation"
"title": "Cancel worksheet evaluation",
"category": "Scala"
}
],
"configurationDefaults": {
Expand Down
29 changes: 5 additions & 24 deletions vscode-dotty/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ import { LanguageClient, LanguageClientOptions, RevealOutputChannelOn,
import { enableOldServerWorkaround } from './compat'
import { WorksheetPublishOutputNotification } from './protocol'
import * as worksheet from './worksheet'
import * as features from './features'

export let client: LanguageClient

let extensionContext: ExtensionContext
let outputChannel: vscode.OutputChannel
export let client: LanguageClient

export function activate(context: ExtensionContext) {
extensionContext = context
Expand All @@ -31,18 +32,6 @@ export function activate(context: ExtensionContext) {
const languageServerDefaultConfigFile = path.join(extensionContext.extensionPath, './out/default-dotty-ide-config')
const coursierPath = path.join(extensionContext.extensionPath, './out/coursier');

vscode.workspace.onWillSaveTextDocument(worksheet.prepareWorksheet)
vscode.workspace.onDidSaveTextDocument(document => {
if (worksheet.isWorksheet(document)) {
worksheet.evaluateWorksheet(document)
}
})
vscode.workspace.onDidCloseTextDocument(document => {
if (worksheet.isWorksheet(document)) {
worksheet.removeWorksheet(document)
}
})

if (process.env['DLS_DEV_MODE']) {
const portFile = `${vscode.workspace.rootPath}/.dotty-ide-dev-port`
fs.readFile(portFile, (err, port) => {
Expand Down Expand Up @@ -203,20 +192,12 @@ function run(serverOptions: ServerOptions, isOldServer: boolean) {
}

client = new LanguageClient("dotty", "Dotty", serverOptions, clientOptions)
client.registerFeature(new features.WorksheetExecFeature(client))

if (isOldServer)
enableOldServerWorkaround(client)

client.onReady().then(() => {
client.onNotification(WorksheetPublishOutputNotification.type, params => {
worksheet.handleMessage(params)
})
})

vscode.commands.registerCommand(worksheet.worksheetEvaluateKey, () => {
worksheet.evaluateWorksheetCommand()
})

// Push the disposable to the context's subscriptions so that the
// client can be deactivated on extension deactivation
extensionContext.subscriptions.push(client.start());
extensionContext.subscriptions.push(client.start())
}
62 changes: 62 additions & 0 deletions vscode-dotty/src/features.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import * as vscode from 'vscode'
import {
BaseLanguageClient, ClientCapabilities, DynamicFeature, ServerCapabilities,
TextDocumentFeature, TextDocumentRegistrationOptions,
} from 'vscode-languageclient'
import { generateUuid } from 'vscode-languageclient/lib/utils/uuid'
import { DocumentSelector } from 'vscode-languageserver-protocol'
import { Disposable } from 'vscode-jsonrpc'

import { WorksheetExecRequest } from './protocol'
import { WorksheetProvider } from './worksheet'

// Remove this if
// https://github.com/Microsoft/vscode-languageserver-node/issues/423 is fixed.
function ensure<T, K extends keyof T>(target: T, key: K): T[K] {
if (target[key] === void 0) {
target[key] = {} as any;
}
return target[key];
}

export interface WorksheetClientCapabilities {
worksheet?: {
exec?: {
dynamicRegistration?: boolean
}
}
}

export interface WorksheetServerCapabilities {
/**
* The server provides support for running worksheets.
*/
worksheetRunProvider?: boolean
}

export class WorksheetExecFeature extends TextDocumentFeature<TextDocumentRegistrationOptions> {
constructor(client: BaseLanguageClient) {
super(client, WorksheetExecRequest.type)
}

public fillClientCapabilities(capabilities: ClientCapabilities & WorksheetClientCapabilities): void {
ensure(ensure(capabilities, "worksheet")!, "exec")!.dynamicRegistration = true
}

public initialize(capabilities: ServerCapabilities & WorksheetServerCapabilities, documentSelector: DocumentSelector): void {
if (!capabilities.worksheetRunProvider) {
return
}

const selector: DocumentSelector = documentSelector || [ { language: 'scala', pattern: '**/*.sc' } ]
this.register(this.messages, {
id: generateUuid(),
registerOptions: { documentSelector: selector }
})
}

protected registerLanguageProvider(options: TextDocumentRegistrationOptions): Disposable {
let client = this._client
return new WorksheetProvider(client, options.documentSelector!)
}
}
Loading

0 comments on commit 0f465e5

Please sign in to comment.