diff options
-rw-r--r-- | editors/code/package.json | 12 | ||||
-rw-r--r-- | editors/code/src/commands/cargo_watch.ts | 102 | ||||
-rw-r--r-- | editors/code/src/commands/runnables.ts | 7 | ||||
-rw-r--r-- | editors/code/src/commands/watch_status.ts | 18 | ||||
-rw-r--r-- | editors/code/src/extension.ts | 16 |
5 files changed, 100 insertions, 55 deletions
diff --git a/editors/code/package.json b/editors/code/package.json index a0454191a..c58171a71 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -119,6 +119,16 @@ | |||
119 | "command": "rust-analyzer.reload", | 119 | "command": "rust-analyzer.reload", |
120 | "title": "Restart server", | 120 | "title": "Restart server", |
121 | "category": "Rust Analyzer" | 121 | "category": "Rust Analyzer" |
122 | }, | ||
123 | { | ||
124 | "command": "rust-analyzer.startCargoWatch", | ||
125 | "title": "Start Cargo Watch", | ||
126 | "category": "Rust Analyzer" | ||
127 | }, | ||
128 | { | ||
129 | "command": "rust-analyzer.stopCargoWatch", | ||
130 | "title": "Stop Cargo Watch", | ||
131 | "category": "Rust Analyzer" | ||
122 | } | 132 | } |
123 | ], | 133 | ], |
124 | "keybindings": [ | 134 | "keybindings": [ |
@@ -253,4 +263,4 @@ | |||
253 | } | 263 | } |
254 | ] | 264 | ] |
255 | } | 265 | } |
256 | } | 266 | } \ No newline at end of file |
diff --git a/editors/code/src/commands/cargo_watch.ts b/editors/code/src/commands/cargo_watch.ts index 32bd38a1c..1d939e28c 100644 --- a/editors/code/src/commands/cargo_watch.ts +++ b/editors/code/src/commands/cargo_watch.ts | |||
@@ -7,44 +7,55 @@ import { terminate } from '../utils/processes'; | |||
7 | import { LineBuffer } from './line_buffer'; | 7 | import { LineBuffer } from './line_buffer'; |
8 | import { StatusDisplay } from './watch_status'; | 8 | import { StatusDisplay } from './watch_status'; |
9 | 9 | ||
10 | export class CargoWatchProvider { | 10 | export function registerCargoWatchProvider( |
11 | private diagnosticCollection?: vscode.DiagnosticCollection; | 11 | subscriptions: vscode.Disposable[] |
12 | private cargoProcess?: child_process.ChildProcess; | 12 | ): CargoWatchProvider | undefined { |
13 | private outBuffer: string = ''; | 13 | let cargoExists = false; |
14 | private statusDisplay?: StatusDisplay; | 14 | const cargoTomlFile = path.join(vscode.workspace.rootPath!, 'Cargo.toml'); |
15 | private outputChannel?: vscode.OutputChannel; | 15 | // Check if the working directory is valid cargo root path |
16 | 16 | try { | |
17 | public activate(subscriptions: vscode.Disposable[]) { | 17 | if (fs.existsSync(cargoTomlFile)) { |
18 | let cargoExists = false; | 18 | cargoExists = true; |
19 | const cargoTomlFile = path.join( | 19 | } |
20 | vscode.workspace.rootPath!, | 20 | } catch (err) { |
21 | 'Cargo.toml' | 21 | cargoExists = false; |
22 | } | ||
23 | |||
24 | if (!cargoExists) { | ||
25 | vscode.window.showErrorMessage( | ||
26 | `Couldn\'t find \'Cargo.toml\' in ${cargoTomlFile}` | ||
22 | ); | 27 | ); |
23 | // Check if the working directory is valid cargo root path | 28 | return; |
24 | try { | 29 | } |
25 | if (fs.existsSync(cargoTomlFile)) { | ||
26 | cargoExists = true; | ||
27 | } | ||
28 | } catch (err) { | ||
29 | cargoExists = false; | ||
30 | } | ||
31 | 30 | ||
32 | if (!cargoExists) { | 31 | const provider = new CargoWatchProvider(); |
33 | vscode.window.showErrorMessage( | 32 | subscriptions.push(provider); |
34 | `Couldn\'t find \'Cargo.toml\' in ${cargoTomlFile}` | 33 | return provider; |
35 | ); | 34 | } |
36 | return; | ||
37 | } | ||
38 | 35 | ||
39 | subscriptions.push(this); | 36 | export class CargoWatchProvider implements vscode.Disposable { |
37 | private readonly diagnosticCollection: vscode.DiagnosticCollection; | ||
38 | private readonly statusDisplay: StatusDisplay; | ||
39 | private readonly outputChannel: vscode.OutputChannel; | ||
40 | private cargoProcess?: child_process.ChildProcess; | ||
41 | |||
42 | constructor() { | ||
40 | this.diagnosticCollection = vscode.languages.createDiagnosticCollection( | 43 | this.diagnosticCollection = vscode.languages.createDiagnosticCollection( |
41 | 'rustc' | 44 | 'rustc' |
42 | ); | 45 | ); |
43 | 46 | this.statusDisplay = new StatusDisplay(); | |
44 | this.statusDisplay = new StatusDisplay(subscriptions); | ||
45 | this.outputChannel = vscode.window.createOutputChannel( | 47 | this.outputChannel = vscode.window.createOutputChannel( |
46 | 'Cargo Watch Trace' | 48 | 'Cargo Watch Trace' |
47 | ); | 49 | ); |
50 | } | ||
51 | |||
52 | public start() { | ||
53 | if (this.cargoProcess) { | ||
54 | vscode.window.showInformationMessage( | ||
55 | 'Cargo Watch is already running' | ||
56 | ); | ||
57 | return; | ||
58 | } | ||
48 | 59 | ||
49 | let args = 'check --message-format json'; | 60 | let args = 'check --message-format json'; |
50 | if (Server.config.cargoWatchOptions.checkArguments.length > 0) { | 61 | if (Server.config.cargoWatchOptions.checkArguments.length > 0) { |
@@ -95,25 +106,28 @@ export class CargoWatchProvider { | |||
95 | this.logInfo('cargo-watch started.'); | 106 | this.logInfo('cargo-watch started.'); |
96 | } | 107 | } |
97 | 108 | ||
98 | public dispose(): void { | 109 | public stop() { |
99 | if (this.diagnosticCollection) { | ||
100 | this.diagnosticCollection.clear(); | ||
101 | this.diagnosticCollection.dispose(); | ||
102 | } | ||
103 | |||
104 | if (this.cargoProcess) { | 110 | if (this.cargoProcess) { |
105 | this.cargoProcess.kill(); | 111 | this.cargoProcess.kill(); |
106 | terminate(this.cargoProcess); | 112 | terminate(this.cargoProcess); |
113 | this.cargoProcess = undefined; | ||
114 | } else { | ||
115 | vscode.window.showInformationMessage('Cargo Watch is not running'); | ||
107 | } | 116 | } |
117 | } | ||
108 | 118 | ||
109 | if (this.outputChannel) { | 119 | public dispose(): void { |
110 | this.outputChannel.dispose(); | 120 | this.stop(); |
111 | } | 121 | |
122 | this.diagnosticCollection.clear(); | ||
123 | this.diagnosticCollection.dispose(); | ||
124 | this.outputChannel.dispose(); | ||
125 | this.statusDisplay.dispose(); | ||
112 | } | 126 | } |
113 | 127 | ||
114 | private logInfo(line: string) { | 128 | private logInfo(line: string) { |
115 | if (Server.config.cargoWatchOptions.trace === 'verbose') { | 129 | if (Server.config.cargoWatchOptions.trace === 'verbose') { |
116 | this.outputChannel!.append(line); | 130 | this.outputChannel.append(line); |
117 | } | 131 | } |
118 | } | 132 | } |
119 | 133 | ||
@@ -122,18 +136,18 @@ export class CargoWatchProvider { | |||
122 | Server.config.cargoWatchOptions.trace === 'error' || | 136 | Server.config.cargoWatchOptions.trace === 'error' || |
123 | Server.config.cargoWatchOptions.trace === 'verbose' | 137 | Server.config.cargoWatchOptions.trace === 'verbose' |
124 | ) { | 138 | ) { |
125 | this.outputChannel!.append(line); | 139 | this.outputChannel.append(line); |
126 | } | 140 | } |
127 | } | 141 | } |
128 | 142 | ||
129 | private parseLine(line: string) { | 143 | private parseLine(line: string) { |
130 | if (line.startsWith('[Running')) { | 144 | if (line.startsWith('[Running')) { |
131 | this.diagnosticCollection!.clear(); | 145 | this.diagnosticCollection.clear(); |
132 | this.statusDisplay!.show(); | 146 | this.statusDisplay.show(); |
133 | } | 147 | } |
134 | 148 | ||
135 | if (line.startsWith('[Finished running')) { | 149 | if (line.startsWith('[Finished running')) { |
136 | this.statusDisplay!.hide(); | 150 | this.statusDisplay.hide(); |
137 | } | 151 | } |
138 | 152 | ||
139 | function getLevel(s: string): vscode.DiagnosticSeverity { | 153 | function getLevel(s: string): vscode.DiagnosticSeverity { |
@@ -193,7 +207,7 @@ export class CargoWatchProvider { | |||
193 | 207 | ||
194 | // The format of the package_id is "{name} {version} ({source_id})", | 208 | // The format of the package_id is "{name} {version} ({source_id})", |
195 | // https://github.com/rust-lang/cargo/blob/37ad03f86e895bb80b474c1c088322634f4725f5/src/cargo/core/package_id.rs#L53 | 209 | // https://github.com/rust-lang/cargo/blob/37ad03f86e895bb80b474c1c088322634f4725f5/src/cargo/core/package_id.rs#L53 |
196 | this.statusDisplay!.packageName = msg.package_id.split(' ')[0]; | 210 | this.statusDisplay.packageName = msg.package_id.split(' ')[0]; |
197 | } else if (data.reason === 'compiler-message') { | 211 | } else if (data.reason === 'compiler-message') { |
198 | const msg = data.message as RustDiagnostic; | 212 | const msg = data.message as RustDiagnostic; |
199 | 213 | ||
diff --git a/editors/code/src/commands/runnables.ts b/editors/code/src/commands/runnables.ts index c4df24c79..5790252b7 100644 --- a/editors/code/src/commands/runnables.ts +++ b/editors/code/src/commands/runnables.ts | |||
@@ -5,7 +5,7 @@ import * as vscode from 'vscode'; | |||
5 | import * as lc from 'vscode-languageclient'; | 5 | import * as lc from 'vscode-languageclient'; |
6 | 6 | ||
7 | import { Server } from '../server'; | 7 | import { Server } from '../server'; |
8 | import { CargoWatchProvider } from './cargo_watch'; | 8 | import { CargoWatchProvider, registerCargoWatchProvider } from './cargo_watch'; |
9 | 9 | ||
10 | interface RunnablesParams { | 10 | interface RunnablesParams { |
11 | textDocument: lc.TextDocumentIdentifier; | 11 | textDocument: lc.TextDocumentIdentifier; |
@@ -137,7 +137,7 @@ export async function handleSingle(runnable: Runnable) { | |||
137 | */ | 137 | */ |
138 | export async function interactivelyStartCargoWatch( | 138 | export async function interactivelyStartCargoWatch( |
139 | context: vscode.ExtensionContext | 139 | context: vscode.ExtensionContext |
140 | ) { | 140 | ): Promise<CargoWatchProvider | undefined> { |
141 | if (Server.config.cargoWatchOptions.enableOnStartup === 'disabled') { | 141 | if (Server.config.cargoWatchOptions.enableOnStartup === 'disabled') { |
142 | return; | 142 | return; |
143 | } | 143 | } |
@@ -197,6 +197,5 @@ export async function interactivelyStartCargoWatch( | |||
197 | } | 197 | } |
198 | } | 198 | } |
199 | 199 | ||
200 | const validater = new CargoWatchProvider(); | 200 | return registerCargoWatchProvider(context.subscriptions); |
201 | validater.activate(context.subscriptions); | ||
202 | } | 201 | } |
diff --git a/editors/code/src/commands/watch_status.ts b/editors/code/src/commands/watch_status.ts index 86ae821de..a3b0178f2 100644 --- a/editors/code/src/commands/watch_status.ts +++ b/editors/code/src/commands/watch_status.ts | |||
@@ -2,19 +2,18 @@ import * as vscode from 'vscode'; | |||
2 | 2 | ||
3 | const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']; | 3 | const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']; |
4 | 4 | ||
5 | export class StatusDisplay { | 5 | export class StatusDisplay implements vscode.Disposable { |
6 | public packageName?: string; | 6 | public packageName?: string; |
7 | 7 | ||
8 | private i = 0; | 8 | private i = 0; |
9 | private statusBarItem: vscode.StatusBarItem; | 9 | private statusBarItem: vscode.StatusBarItem; |
10 | private timer?: NodeJS.Timeout; | 10 | private timer?: NodeJS.Timeout; |
11 | 11 | ||
12 | constructor(subscriptions: vscode.Disposable[]) { | 12 | constructor() { |
13 | this.statusBarItem = vscode.window.createStatusBarItem( | 13 | this.statusBarItem = vscode.window.createStatusBarItem( |
14 | vscode.StatusBarAlignment.Left, | 14 | vscode.StatusBarAlignment.Left, |
15 | 10 | 15 | 10 |
16 | ); | 16 | ); |
17 | subscriptions.push(this.statusBarItem); | ||
18 | this.statusBarItem.hide(); | 17 | this.statusBarItem.hide(); |
19 | } | 18 | } |
20 | 19 | ||
@@ -33,7 +32,7 @@ export class StatusDisplay { | |||
33 | } | 32 | } |
34 | }, 300); | 33 | }, 300); |
35 | 34 | ||
36 | this.statusBarItem!.show(); | 35 | this.statusBarItem.show(); |
37 | } | 36 | } |
38 | 37 | ||
39 | public hide() { | 38 | public hide() { |
@@ -42,7 +41,16 @@ export class StatusDisplay { | |||
42 | this.timer = undefined; | 41 | this.timer = undefined; |
43 | } | 42 | } |
44 | 43 | ||
45 | this.statusBarItem!.hide(); | 44 | this.statusBarItem.hide(); |
45 | } | ||
46 | |||
47 | public dispose() { | ||
48 | if (this.timer) { | ||
49 | clearInterval(this.timer); | ||
50 | this.timer = undefined; | ||
51 | } | ||
52 | |||
53 | this.statusBarItem.dispose(); | ||
46 | } | 54 | } |
47 | 55 | ||
48 | private frame() { | 56 | private frame() { |
diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index 1073a36a0..b48ad9b29 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts | |||
@@ -2,6 +2,7 @@ import * as vscode from 'vscode'; | |||
2 | import * as lc from 'vscode-languageclient'; | 2 | import * as lc from 'vscode-languageclient'; |
3 | 3 | ||
4 | import * as commands from './commands'; | 4 | import * as commands from './commands'; |
5 | import { CargoWatchProvider } from './commands/cargo_watch'; | ||
5 | import { interactivelyStartCargoWatch } from './commands/runnables'; | 6 | import { interactivelyStartCargoWatch } from './commands/runnables'; |
6 | import { SyntaxTreeContentProvider } from './commands/syntaxTree'; | 7 | import { SyntaxTreeContentProvider } from './commands/syntaxTree'; |
7 | import * as events from './events'; | 8 | import * as events from './events'; |
@@ -126,7 +127,20 @@ export function activate(context: vscode.ExtensionContext) { | |||
126 | vscode.commands.registerCommand('rust-analyzer.reload', reloadCommand); | 127 | vscode.commands.registerCommand('rust-analyzer.reload', reloadCommand); |
127 | 128 | ||
128 | // Executing `cargo watch` provides us with inline diagnostics on save | 129 | // Executing `cargo watch` provides us with inline diagnostics on save |
129 | interactivelyStartCargoWatch(context); | 130 | let provider: CargoWatchProvider | undefined; |
131 | interactivelyStartCargoWatch(context).then(p => { | ||
132 | provider = p; | ||
133 | }); | ||
134 | registerCommand('rust-analyzer.startCargoWatch', () => { | ||
135 | if (provider) { | ||
136 | provider.start(); | ||
137 | } | ||
138 | }); | ||
139 | registerCommand('rust-analyzer.stopCargoWatch', () => { | ||
140 | if (provider) { | ||
141 | provider.stop(); | ||
142 | } | ||
143 | }); | ||
130 | 144 | ||
131 | // Start the language server, finally! | 145 | // Start the language server, finally! |
132 | startServer(); | 146 | startServer(); |