-
Notifications
You must be signed in to change notification settings - Fork 114
/
install.ts
134 lines (123 loc) · 4.98 KB
/
install.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Automatically install clangd binary releases from GitHub.
// This wraps `@clangd/install` in the VSCode UI. See that package for more.
import * as common from '@clangd/install';
import AbortController from 'abort-controller';
import * as path from 'path';
import * as vscode from 'vscode';
import * as config from './config';
// Returns the clangd path to be used, or null if clangd is not installed.
export async function activate(disposables: vscode.Disposable[],
globalStoragePath: string):
Promise<string|null> {
const ui = new UI(disposables, globalStoragePath);
disposables.push(vscode.commands.registerCommand(
'clangd.install', async () => common.installLatest(ui)));
disposables.push(vscode.commands.registerCommand(
'clangd.update', async () => common.checkUpdates(true, ui)));
const status = await common.prepare(ui, config.get<boolean>('checkUpdates'));
return status.clangdPath;
}
class UI {
constructor(private disposables: vscode.Disposable[],
private globalStoragePath: string) {}
get storagePath(): string { return this.globalStoragePath; }
async choose(prompt: string, options: string[]): Promise<string|undefined> {
return await vscode.window.showInformationMessage(prompt, ...options);
}
slow<T>(title: string, result: Promise<T>) {
const opts = {
location: vscode.ProgressLocation.Notification,
title: title,
cancellable: false,
};
return Promise.resolve(vscode.window.withProgress(opts, () => result));
}
progress<T>(title: string, cancel: AbortController|null,
body: (progress: (fraction: number) => void) => Promise<T>) {
const opts = {
location: vscode.ProgressLocation.Notification,
title: title,
cancellable: cancel !== null,
};
const result = vscode.window.withProgress(opts, async (progress, canc) => {
if (cancel)
canc.onCancellationRequested((_) => cancel.abort());
let lastFraction = 0;
return body(fraction => {
if (fraction > lastFraction) {
progress.report({increment: 100 * (fraction - lastFraction)});
lastFraction = fraction;
}
});
});
return Promise.resolve(result); // Thenable to real promise.
}
error(s: string) { vscode.window.showErrorMessage(s); }
info(s: string) { vscode.window.showInformationMessage(s); }
command(name: string, body: () => any) {
this.disposables.push(vscode.commands.registerCommand(name, body));
}
async shouldReuse(release: string): Promise<boolean|undefined> {
const message = `clangd ${release} is already installed!`;
const use = 'Use the installed version';
const reinstall = 'Delete it and reinstall';
const response =
await vscode.window.showInformationMessage(message, use, reinstall);
if (response === use) {
// Find clangd within the existing directory.
return true;
} else if (response === reinstall) {
// Remove the existing installation.
return false;
} else {
// User dismissed prompt, bail out.
return undefined;
}
}
async promptReload(message: string) {
if (await vscode.window.showInformationMessage(message, 'Reload window'))
vscode.commands.executeCommand('workbench.action.reloadWindow');
}
async showHelp(message: string, url: string) {
if (await vscode.window.showInformationMessage(message, 'Open website'))
vscode.env.openExternal(vscode.Uri.parse(url));
}
async promptUpdate(oldVersion: string, newVersion: string) {
const message = 'An updated clangd language server is available.\n ' +
`Would you like to upgrade to clangd ${newVersion}? ` +
`(from ${oldVersion})`;
const update = `Install clangd ${newVersion}`;
const dontCheck = 'Don\'t ask again';
const response =
await vscode.window.showInformationMessage(message, update, dontCheck);
if (response === update) {
common.installLatest(this);
} else if (response === dontCheck) {
config.update('checkUpdates', false, vscode.ConfigurationTarget.Global);
}
}
async promptInstall(version: string) {
const p = this.clangdPath;
let message = '';
if (p.indexOf(path.sep) < 0) {
message += `The '${p}' language server was not found on your PATH.\n`;
} else {
message += `The clangd binary '${p}' was not found.\n`;
}
message += `Would you like to download and install clangd ${version}?`;
if (await vscode.window.showInformationMessage(message, 'Install'))
common.installLatest(this);
}
get clangdPath(): string {
let p = config.get<string>('path')!;
// Backwards compatibility: if it's a relative path with a slash, interpret
// relative to project root.
if (!path.isAbsolute(p) && p.includes(path.sep) &&
vscode.workspace.rootPath !== undefined)
p = path.join(vscode.workspace.rootPath, p);
return p;
}
set clangdPath(p: string) {
config.update('path', p, vscode.ConfigurationTarget.Global);
}
}