Skip to content
This repository was archived by the owner on Jun 22, 2024. It is now read-only.

Commit b83f0d9

Browse files
committed
Encapsulate LSP client for restart
1 parent 92a668e commit b83f0d9

File tree

5 files changed

+111
-83
lines changed

5 files changed

+111
-83
lines changed

src/clientMain.ts

Lines changed: 16 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
11
"use strict";
22

3-
import * as path from "path";
43
import * as fs from "fs";
54
import * as tools from "./SwiftTools";
5+
import * as path from "path";
66
import {
7-
workspace,
8-
window,
97
commands,
10-
languages,
11-
ExtensionContext,
128
DiagnosticCollection,
13-
OutputChannel,
9+
ExtensionContext,
10+
languages,
1411
TextDocument,
12+
window,
13+
workspace,
1514
} from "vscode";
16-
import { LanguageClient, LanguageClientOptions, ServerOptions } from "vscode-languageclient";
17-
import { absolutePath } from "./AbsolutePath";
18-
19-
import * as config from "./config-helpers";
20-
import output from "./output-channels";
21-
import { LangaugeServerMode } from "./config-helpers";
22-
23-
import { statusBarItem } from "./status-bar";
15+
import { absolutePath } from "./helpers/AbsolutePath";
16+
import * as config from "./vscode/config-helpers";
17+
import lsp from "./vscode/lsp-interop";
18+
import output from "./vscode/output-channels";
19+
import { statusBarItem } from "./vscode/status-bar";
2420

2521
let swiftBinPath: string | null = null;
2622
let swiftBuildParams: string[] = ["build"];
@@ -39,47 +35,17 @@ export function activate(context: ExtensionContext) {
3935
output.build.log("Activating SDE");
4036

4137
initConfig();
42-
43-
// Options to control the language client
44-
let clientOptions: LanguageClientOptions = {
45-
// Register the server for plain text documents
46-
documentSelector: [
47-
{ language: "swift", scheme: "file" },
48-
{ pattern: "*.swift", scheme: "file" },
49-
],
50-
synchronize: {
51-
configurationSection: ["swift", "editor", "[swift]"],
52-
// Notify the server about file changes to '.clientrc files contain in the workspace
53-
fileEvents: [
54-
workspace.createFileSystemWatcher("**/*.swift"),
55-
workspace.createFileSystemWatcher(".build/*.yaml"),
56-
],
57-
},
58-
initializationOptions: {
59-
isLSPServerTracingOn: config.isLSPTracingOn(), // used by sourcekites
60-
skProtocolProcess,
61-
skProtocolProcessAsShellCmd,
62-
skCompilerOptions: workspace.getConfiguration().get("sde.sourcekit.compilerOptions"),
63-
toolchainPath:
64-
workspace.getConfiguration("sourcekit-lsp").get<string>("toolchainPath") || null,
65-
},
66-
...currentClientOptions(context),
67-
};
68-
69-
// Create the language client and start the client.
70-
const lspOpts = currentServerOptions(context);
71-
const langClient = new LanguageClient("Swift", lspOpts, clientOptions);
72-
context.subscriptions.push(langClient.start());
38+
lsp.startLSPClient(context);
7339

7440
diagnosticCollection = languages.createDiagnosticCollection("swift");
7541
context.subscriptions.push(diagnosticCollection);
7642

7743
//commands
7844
context.subscriptions.push(
7945
commands.registerCommand("sde.commands.buildPackage", buildSPMPackage),
80-
commands.registerCommand("sde.commands.restartLanguageServer", () => {
81-
output.build.log("sde.commands.restartLanguageServer");
82-
}),
46+
commands.registerCommand("sde.commands.restartLanguageServer", () =>
47+
lsp.restartLSPClient(context)
48+
),
8349
commands.registerCommand("sde.commands.runPackage", () => {
8450
output.build.log("sde.commands.runPackage");
8551
})
@@ -102,38 +68,14 @@ function initConfig() {
10268
checkToolsAvailability();
10369

10470
//FIXME rootPath may be undefined for adhoc file editing mode???
105-
swiftPackageManifestPath = workspace.rootPath
106-
? path.join(workspace.rootPath, "Package.swift")
71+
swiftPackageManifestPath = workspace.workspaceFolders[0]
72+
? path.join(workspace.workspaceFolders[0].uri.fsPath, "Package.swift")
10773
: null;
10874
}
10975

110-
function currentServerOptions(context: ExtensionContext): ServerOptions {
111-
switch (config.lsp()) {
112-
case LangaugeServerMode.LanguageServer:
113-
return config.lspServerOptions(context);
114-
case LangaugeServerMode.SourceKit:
115-
return config.sourcekitLspServerOptions(context);
116-
case LangaugeServerMode.SourceKite:
117-
return config.sourcekiteServerOptions(context);
118-
}
119-
}
120-
121-
function currentClientOptions(_context: ExtensionContext): Partial<LanguageClientOptions> {
122-
switch (config.lsp()) {
123-
case LangaugeServerMode.SourceKit:
124-
return {
125-
documentSelector: ["swift", "cpp", "c", "objective-c", "objective-cpp"],
126-
synchronize: undefined,
127-
};
128-
default:
129-
return {};
130-
}
131-
}
132-
13376
function buildSPMPackage() {
13477
if (isSPMProject()) {
13578
statusBarItem.start();
136-
output.build.log("Starting package build");
13779
tools.buildPackage(swiftBinPath, workspace.rootPath, swiftBuildParams);
13880
}
13981
}

src/SwiftTools.ts renamed to src/toolchain/SwiftTools.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
"use strict";
22

33
import { Diagnostic, DiagnosticSeverity, Range, Uri, window as vscodeWindow } from "vscode";
4-
import { diagnosticCollection } from "./clientMain";
5-
import { isBuildTracingOn } from "./config-helpers";
6-
import output from "./output-channels";
7-
import { statusBarItem } from "./status-bar";
4+
import { diagnosticCollection } from "../clientMain";
5+
import { isBuildTracingOn } from "../vscode/config-helpers";
6+
import output from "../vscode/output-channels";
7+
import { statusBarItem } from "../vscode/status-bar";
88
import cp = require("child_process");
99

1010
function trace(...msg: any[]) {
@@ -13,13 +13,18 @@ function trace(...msg: any[]) {
1313
}
1414
}
1515

16+
/** parsed to generate diagnostics */
17+
let buildOutput = "";
18+
1619
///managed build now only support to invoke on save
1720
export function buildPackage(swiftBinPath: string, pkgPath: string, params: string[]) {
21+
buildOutput = "";
1822
output.build.log("Build Started");
1923
const buildProc = cp.spawn(swiftBinPath, params, { cwd: pkgPath, shell: true });
2024
buildProc.stdout.on("data", data => {
2125
const msg = `${data}`.trim();
2226
if (msg.length) {
27+
buildOutput += data;
2328
output.build.log(msg);
2429
}
2530
});
@@ -60,7 +65,7 @@ export function buildPackage(swiftBinPath: string, pkgPath: string, params: stri
6065
function dumpDiagnostics() {
6166
const diagnosticMap: Map<string, Diagnostic[]> = new Map();
6267
let diags: Array<string[]> = [];
63-
const lines = stdout.split("\n");
68+
const lines = buildOutput.split("\n");
6469

6570
function isDiagStartLine(line: string) {
6671
//FIXME

src/vscode/config-helpers.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export function isLSPTracingOn(): boolean {
4242
*/
4343
export function sourcekiteServerOptions(context: ExtensionContext): ServerOptions {
4444
// The server is implemented in node
45-
const serverModule = context.asAbsolutePath(path.join("out/src/server", "server.js"));
45+
const serverModule = context.asAbsolutePath(path.join("out/src/sourcekites-server", "server.js"));
4646
// The debug options for the server
4747
const debugOptions = {
4848
execArgv: ["--nolazy", "--inspect=6004"],
@@ -66,7 +66,7 @@ export function sourcekiteServerOptions(context: ExtensionContext): ServerOption
6666
return serverOptions;
6767
}
6868

69-
export function lspServerOptions(context: ExtensionContext): ServerOptions {
69+
export function lspServerOptions(): ServerOptions {
7070
// Load the path to the language server from settings
7171
const executableCommand = workspace
7272
.getConfiguration("swift")
@@ -84,7 +84,7 @@ export function lspServerOptions(context: ExtensionContext): ServerOptions {
8484
return serverOptions;
8585
}
8686

87-
export function sourcekitLspServerOptions(context: ExtensionContext): ServerOptions {
87+
export function sourcekitLspServerOptions(): ServerOptions {
8888
const toolchain = workspace.getConfiguration("sourcekit-lsp").get<string>("toolchainPath");
8989

9090
const sourcekitPath = sourceKitLSPLocation(toolchain);

src/vscode/lang-client.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/vscode/lsp-interop.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { workspace, ExtensionContext, Disposable } from "vscode";
2+
import { LanguageClient, LanguageClientOptions, ServerOptions } from "vscode-languageclient";
3+
import * as config from "./config-helpers";
4+
import { LangaugeServerMode } from "./config-helpers";
5+
6+
function currentServerOptions(context: ExtensionContext): ServerOptions {
7+
switch (config.lsp()) {
8+
case LangaugeServerMode.LanguageServer:
9+
return config.lspServerOptions();
10+
case LangaugeServerMode.SourceKit:
11+
return config.sourcekitLspServerOptions();
12+
case LangaugeServerMode.SourceKite:
13+
return config.sourcekiteServerOptions(context);
14+
}
15+
}
16+
17+
function currentClientOptions(): Partial<LanguageClientOptions> {
18+
switch (config.lsp()) {
19+
case LangaugeServerMode.SourceKit:
20+
return {
21+
documentSelector: ["swift", "cpp", "c", "objective-c", "objective-cpp"],
22+
synchronize: undefined,
23+
};
24+
default:
25+
return {};
26+
}
27+
}
28+
29+
let lspClient: LanguageClient | undefined;
30+
let clientDisposable: Disposable | undefined;
31+
32+
/**
33+
* Starts the LSP client (which specifies how to start the LSP server), and registers
34+
* a dispoasble in the extension context.
35+
* @param context the SDE extension context
36+
*/
37+
function startLSPClient(context: ExtensionContext) {
38+
let clientOptions: LanguageClientOptions = {
39+
// Register the server for plain text documentss
40+
documentSelector: [
41+
{ language: "swift", scheme: "file" },
42+
{ pattern: "*.swift", scheme: "file" },
43+
],
44+
synchronize: {
45+
configurationSection: ["swift", "editor", "[swift]"],
46+
// Notify the server about file changes to '.clientrc files contain in the workspace
47+
fileEvents: [
48+
workspace.createFileSystemWatcher("**/*.swift"),
49+
workspace.createFileSystemWatcher(".build/*.yaml"),
50+
],
51+
},
52+
initializationOptions: {
53+
// isLSPServerTracingOn: config.isLSPTracingOn(), // used by sourcekite
54+
// skProtocolProcess, // used by sourcekite
55+
// skProtocolProcessAsShellCmd, // used by sourcekite
56+
// skCompilerOptions: workspace.getConfiguration().get("sde.sourcekit.compilerOptions"), // used by sourcekite
57+
// toolchainPath:
58+
// workspace.getConfiguration("sourcekit-lsp").get<string>("toolchainPath") || null,
59+
},
60+
...currentClientOptions(),
61+
};
62+
// Create the language client and start the client.
63+
const lspOpts = currentServerOptions(context);
64+
lspClient = new LanguageClient("Swift", lspOpts, clientOptions);
65+
clientDisposable = lspClient.start();
66+
context.subscriptions.push(clientDisposable);
67+
}
68+
69+
/**
70+
* Stops the current LSP client and starts a new client.
71+
* The client is stopped using the disposable returned from `client.start()`
72+
* @param context the SDE extension context
73+
*/
74+
function restartLSPClient(context: ExtensionContext) {
75+
clientDisposable.dispose();
76+
startLSPClient(context);
77+
}
78+
79+
export default {
80+
startLSPClient,
81+
restartLSPClient,
82+
};

0 commit comments

Comments
 (0)