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

Commit 9bf4fd2

Browse files
committed
Better and more helpful error messages on first start
1 parent a498576 commit 9bf4fd2

File tree

5 files changed

+196
-35
lines changed

5 files changed

+196
-35
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
- Better and more helpful error messages on first start
6+
57
## 2.11.1
68

79
- [Disable C and C++ for sourcekit-lsp](https://forums.swift.org/t/disable-sourcekit-lsp-for-c-files/30717/3)

src/clientMain.ts

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import * as fs from "fs";
44
import * as path from "path";
5-
import { commands, DiagnosticCollection, ExtensionContext, window, workspace } from "vscode";
5+
import { commands, DiagnosticCollection, ExtensionContext, Uri, window, workspace } from "vscode";
66
import { absolutePath } from "./helpers/AbsolutePath";
77
import * as tools from "./toolchain/SwiftTools";
88
import * as config from "./vscode/config-helpers";
@@ -18,7 +18,7 @@ export let diagnosticCollection: DiagnosticCollection;
1818

1919
let mostRecentRunTarget = "";
2020

21-
export function activate(context: ExtensionContext) {
21+
export async function activate(context: ExtensionContext) {
2222
output.init(context);
2323

2424
if (workspace.getConfiguration().get<boolean>("sde.enable") === false) {
@@ -28,8 +28,8 @@ export function activate(context: ExtensionContext) {
2828
tools.setRunning(false);
2929
output.build.log("Activating SDE");
3030

31-
initConfig();
32-
lsp.startLSPClient(context);
31+
await initConfig();
32+
await lsp.startLSPClient(context);
3333

3434
//commands
3535
let toolchain = new tools.Toolchain(
@@ -41,8 +41,9 @@ export function activate(context: ExtensionContext) {
4141
context.subscriptions.push(toolchain.start());
4242
context.subscriptions.push(
4343
commands.registerCommand("sde.commands.build", () => toolchain.build()),
44-
commands.registerCommand("sde.commands.restartLanguageServer", () =>
45-
lsp.restartLSPClient(context)
44+
commands.registerCommand(
45+
"sde.commands.restartLanguageServer",
46+
async () => await lsp.restartLSPClient(context)
4647
),
4748
commands.registerCommand("sde.commands.run", () => toolchain.runStart()),
4849
commands.registerCommand("sde.commands.selectRun", () => {
@@ -75,21 +76,25 @@ export function activate(context: ExtensionContext) {
7576
);
7677

7778
// respond to settings changes
78-
workspace.onDidChangeConfiguration(event => {
79-
if (event.affectsConfiguration("sde")) {
80-
// reload things as necessary
79+
workspace.onDidChangeConfiguration(async event => {
80+
if (
81+
event.affectsConfiguration("sde") ||
82+
event.affectsConfiguration("swift") ||
83+
event.affectsConfiguration("sourcekit-lsp")
84+
) {
85+
await lsp.restartLSPClient(context);
8186
}
8287
});
8388

8489
// build on startup
8590
toolchain.build();
8691
}
8792

88-
function initConfig() {
93+
async function initConfig() {
8994
checkToolsAvailability();
9095
}
9196

92-
function checkToolsAvailability() {
97+
async function checkToolsAvailability() {
9398
swiftBinPath = absolutePath(workspace.getConfiguration().get("swift.path.swift_driver_bin"));
9499
swiftBuildParams = <string[]>workspace.getConfiguration().get("sde.swiftBuildingParams") || [
95100
"build",
@@ -102,21 +107,29 @@ function checkToolsAvailability() {
102107
skProtocolProcess = sourcekitePath;
103108
skProtocolProcessAsShellCmd = sourcekitePathEnableShCmd;
104109

105-
if (!swiftBinPath || !fs.existsSync(swiftBinPath)) {
106-
window.showErrorMessage(
107-
'missing dependent `swift` tool, please configure correct "swift.path.swift_driver_bin"'
108-
);
109-
}
110-
if (!sourcekitePathEnableShCmd) {
111-
if (!skProtocolProcess || !fs.existsSync(skProtocolProcess)) {
112-
window.showErrorMessage(
113-
'missing dependent sourcekite tool, please configure correct "swift.path.sourcekite"'
114-
);
115-
}
116-
}
117-
if (!shellPath || !fs.existsSync(shellPath)) {
118-
window.showErrorMessage(
119-
'missing dependent shell tool, please configure correct "swift.path.shell"'
120-
);
121-
}
110+
// if (!swiftBinPath || !fs.existsSync(swiftBinPath)) {
111+
// window.showErrorMessage(
112+
// 'missing dependent `swift` tool, please configure correct "swift.path.swift_driver_bin"'
113+
// );
114+
// }
115+
// if (!sourcekitePathEnableShCmd) {
116+
// if (!skProtocolProcess || !fs.existsSync(skProtocolProcess)) {
117+
// const action = await window.showErrorMessage(
118+
// `\`sourcekite\` not found at \`${skProtocolProcess}\`.
119+
// Install it and provide the path to \`swift.path.sourcekite\`.`,
120+
// 'Retry', 'Help'
121+
// );
122+
// if (action === "Help") {
123+
// await commands.executeCommand(
124+
// "vscode.open",
125+
// Uri.parse("https://github.com/vknabel/vscode-swift-development-environment/tree/2.11.1#using-sourcekite")
126+
// );
127+
// }
128+
// }
129+
// }
130+
// if (!shellPath || !fs.existsSync(shellPath)) {
131+
// window.showErrorMessage(
132+
// 'missing dependent shell tool, please configure correct "swift.path.shell"'
133+
// );
134+
// }
122135
}

src/vscode/config-helpers.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,14 @@ export function sourcekiteServerOptions(context: ExtensionContext): ServerOption
6666
return serverOptions;
6767
}
6868

69-
export function lspServerOptions(): ServerOptions {
70-
// Load the path to the language server from settings
71-
const executableCommand = workspace
69+
export function languageServerPath(): string {
70+
return workspace
7271
.getConfiguration("swift")
7372
.get("languageServerPath", "/usr/local/bin/LanguageServer");
73+
}
74+
export function lspServerOptions(): ServerOptions {
75+
// Load the path to the language server from settings
76+
const executableCommand = languageServerPath();
7477

7578
const run: Executable = {
7679
command: executableCommand,
@@ -84,6 +87,9 @@ export function lspServerOptions(): ServerOptions {
8487
return serverOptions;
8588
}
8689

90+
export function toolchainPath(): string {
91+
return workspace.getConfiguration("sourcekit-lsp").get<string>("toolchainPath");
92+
}
8793
export function sourcekitLspServerOptions(): ServerOptions {
8894
const toolchain = workspace.getConfiguration("sourcekit-lsp").get<string>("toolchainPath");
8995

@@ -108,7 +114,7 @@ export function sourcekitLspServerOptions(): ServerOptions {
108114
return serverOptions;
109115
}
110116

111-
function sourceKitLSPLocation(toolchain: string | undefined): string {
117+
export function sourceKitLSPLocation(toolchain: string | undefined): string {
112118
const explicit = workspace
113119
.getConfiguration("sourcekit-lsp")
114120
.get<string | null>("serverPath", null);

src/vscode/lsp-interop.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { LanguageClient, LanguageClientOptions, ServerOptions } from "vscode-lan
33
import { absolutePath } from "../helpers/AbsolutePath";
44
import * as config from "./config-helpers";
55
import { LangaugeServerMode } from "./config-helpers";
6+
import { currentLspPreconditions } from "./lsp-preconditions";
67

78
function currentServerOptions(context: ExtensionContext): ServerOptions {
89
switch (config.lsp()) {
@@ -50,7 +51,8 @@ let clientDisposable: Disposable | undefined;
5051
* a dispoasble in the extension context.
5152
* @param context the SDE extension context
5253
*/
53-
function startLSPClient(context: ExtensionContext) {
54+
async function startLSPClient(context: ExtensionContext) {
55+
await currentLspPreconditions();
5456
let clientOptions: LanguageClientOptions = {
5557
// Register the server for plain text documentss
5658
documentSelector: [
@@ -79,9 +81,9 @@ function startLSPClient(context: ExtensionContext) {
7981
* The client is stopped using the disposable returned from `client.start()`
8082
* @param context the SDE extension context
8183
*/
82-
function restartLSPClient(context: ExtensionContext) {
84+
async function restartLSPClient(context: ExtensionContext) {
8385
clientDisposable.dispose();
84-
startLSPClient(context);
86+
await startLSPClient(context);
8587
}
8688

8789
export default {

src/vscode/lsp-preconditions.ts

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import { commands, Uri, window, workspace } from "vscode";
2+
import { absolutePath } from "../helpers/AbsolutePath";
3+
import * as config from "./config-helpers";
4+
import { LangaugeServerMode } from "./config-helpers";
5+
import * as fs from "fs";
6+
7+
export async function currentLspPreconditions(): Promise<void> {
8+
await generalPreconditions();
9+
switch (config.lsp()) {
10+
case LangaugeServerMode.LanguageServer:
11+
return currentLanguageServerPreconditions();
12+
case LangaugeServerMode.SourceKit:
13+
return currentSourcekitLspPreconditions();
14+
case LangaugeServerMode.SourceKite:
15+
return currentSourcekitePreconditions();
16+
}
17+
}
18+
19+
enum PreconditionActions {
20+
Retry = "Retry",
21+
OpenSettings = "Settings",
22+
InstructionsSourcekitLsp = "Help for sourcekit-lsp",
23+
InstructionsSourcekite = "Help for sourcekite",
24+
InstructionsLangserver = "Help for LangserverSwift",
25+
}
26+
27+
async function generalPreconditions(): Promise<void> {
28+
const shellPath = absolutePath(workspace.getConfiguration().get("swift.path.shell"));
29+
if (!shellPath || !fs.existsSync(shellPath)) {
30+
await handlePreconditionAction(
31+
await window.showErrorMessage(
32+
`Wrong shell path ${shellPath} for setting swift.path.shell.`,
33+
PreconditionActions.Retry,
34+
PreconditionActions.OpenSettings
35+
)
36+
);
37+
}
38+
39+
const swiftPath = absolutePath(workspace.getConfiguration().get("swift.path.swift_driver_bin"));
40+
if (!swiftPath || !fs.existsSync(swiftPath)) {
41+
await handlePreconditionAction(
42+
await window.showErrorMessage(
43+
`Swift not found at path ${swiftPath} for setting swift.path.swift_driver_bin`,
44+
PreconditionActions.Retry,
45+
PreconditionActions.OpenSettings
46+
)
47+
);
48+
}
49+
}
50+
51+
async function currentLanguageServerPreconditions(): Promise<void> {
52+
const lspPath = config.languageServerPath();
53+
if (!fs.existsSync(lspPath)) {
54+
await handlePreconditionAction(
55+
await window.showErrorMessage(
56+
`Langserver not found at \`${lspPath}\`.
57+
Install it and provide the path to \`swift.languageServerPath\`.`,
58+
PreconditionActions.Retry,
59+
PreconditionActions.OpenSettings,
60+
PreconditionActions.InstructionsLangserver
61+
)
62+
);
63+
}
64+
}
65+
66+
async function currentSourcekitLspPreconditions(): Promise<void> {
67+
const sourcekitLspPath = config.sourceKitLSPLocation(config.toolchainPath());
68+
69+
if (!fs.existsSync(sourcekitLspPath)) {
70+
await handlePreconditionAction(
71+
await window.showErrorMessage(
72+
`sourcekit-lsp not found at \`${sourcekitLspPath}\`.
73+
Install it and provide the path to \`sourcekit-lsp.serverPath\`.`,
74+
PreconditionActions.Retry,
75+
PreconditionActions.OpenSettings,
76+
PreconditionActions.InstructionsSourcekitLsp
77+
)
78+
);
79+
}
80+
}
81+
82+
async function currentSourcekitePreconditions(): Promise<void> {
83+
const isDockerMode = workspace
84+
.getConfiguration()
85+
.get<boolean>("swift.path.sourcekiteDockerMode", false);
86+
const sourcekitePath = absolutePath(workspace.getConfiguration().get("swift.path.sourcekite"));
87+
88+
if (!isDockerMode && !fs.existsSync(sourcekitePath)) {
89+
await handlePreconditionAction(
90+
await window.showErrorMessage(
91+
`\`sourcekite\` not found at \`${sourcekitePath}\`.
92+
Install it and provide the path to \`swift.path.sourcekite\`.`,
93+
PreconditionActions.Retry,
94+
PreconditionActions.OpenSettings,
95+
PreconditionActions.InstructionsSourcekite
96+
)
97+
);
98+
}
99+
}
100+
101+
async function handlePreconditionAction(
102+
action: string | PreconditionActions | undefined
103+
): Promise<void> {
104+
switch (action) {
105+
case PreconditionActions.Retry:
106+
await currentLspPreconditions();
107+
break;
108+
case PreconditionActions.OpenSettings:
109+
if (action === "Settings") {
110+
await commands.executeCommand("workbench.action.openSettings");
111+
}
112+
break;
113+
case PreconditionActions.InstructionsSourcekite:
114+
await commands.executeCommand(
115+
"vscode.open",
116+
Uri.parse(
117+
"https://github.com/vknabel/vscode-swift-development-environment/tree/2.11.1#using-sourcekit-lsp"
118+
)
119+
);
120+
break;
121+
case PreconditionActions.InstructionsSourcekitLsp:
122+
await commands.executeCommand(
123+
"vscode.open",
124+
Uri.parse(
125+
"https://github.com/vknabel/vscode-swift-development-environment/tree/2.11.1#using-sourcekite"
126+
)
127+
);
128+
break;
129+
case PreconditionActions.InstructionsLangserver:
130+
await commands.executeCommand(
131+
"vscode.open",
132+
Uri.parse(
133+
"https://github.com/vknabel/vscode-swift-development-environment/tree/2.11.1#using-langserver-swift"
134+
)
135+
);
136+
break;
137+
}
138+
}

0 commit comments

Comments
 (0)