mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Re-implement status display using LSP 3.15 progress event
This commit is contained in:
parent
500fe46e6c
commit
178c23f505
4 changed files with 103 additions and 9 deletions
|
@ -9,7 +9,8 @@ use cargo_metadata::{
|
|||
use crossbeam_channel::{select, unbounded, Receiver, RecvError, Sender, TryRecvError};
|
||||
use lsp_types::{
|
||||
Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, DiagnosticTag, Location,
|
||||
NumberOrString, Position, Range, Url,
|
||||
NumberOrString, Position, Range, Url, WorkDoneProgress, WorkDoneProgressBegin,
|
||||
WorkDoneProgressEnd, WorkDoneProgressReport,
|
||||
};
|
||||
use parking_lot::RwLock;
|
||||
use std::{
|
||||
|
@ -132,6 +133,7 @@ impl CheckWatcherSharedState {
|
|||
#[derive(Debug)]
|
||||
pub enum CheckTask {
|
||||
Update(Url),
|
||||
Status(WorkDoneProgress),
|
||||
}
|
||||
|
||||
pub enum CheckCommand {
|
||||
|
@ -204,13 +206,38 @@ impl CheckWatcherState {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_message(&mut self, msg: cargo_metadata::Message, task_send: &Sender<CheckTask>) {
|
||||
fn handle_message(&mut self, msg: CheckEvent, task_send: &Sender<CheckTask>) {
|
||||
match msg {
|
||||
Message::CompilerArtifact(_msg) => {
|
||||
// TODO: Status display
|
||||
CheckEvent::Begin => {
|
||||
task_send
|
||||
.send(CheckTask::Status(WorkDoneProgress::Begin(WorkDoneProgressBegin {
|
||||
title: "Running 'cargo check'".to_string(),
|
||||
cancellable: Some(false),
|
||||
message: None,
|
||||
percentage: None,
|
||||
})))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
Message::CompilerMessage(msg) => {
|
||||
CheckEvent::End => {
|
||||
task_send
|
||||
.send(CheckTask::Status(WorkDoneProgress::End(WorkDoneProgressEnd {
|
||||
message: None,
|
||||
})))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
CheckEvent::Msg(Message::CompilerArtifact(msg)) => {
|
||||
task_send
|
||||
.send(CheckTask::Status(WorkDoneProgress::Report(WorkDoneProgressReport {
|
||||
cancellable: Some(false),
|
||||
message: Some(msg.target.name),
|
||||
percentage: None,
|
||||
})))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
CheckEvent::Msg(Message::CompilerMessage(msg)) => {
|
||||
let map_result =
|
||||
match map_rust_diagnostic_to_lsp(&msg.message, &self.workspace_root) {
|
||||
Some(map_result) => map_result,
|
||||
|
@ -232,8 +259,8 @@ impl CheckWatcherState {
|
|||
task_send.send(CheckTask::Update(location.uri)).unwrap();
|
||||
}
|
||||
|
||||
Message::BuildScriptExecuted(_msg) => {}
|
||||
Message::Unknown => {}
|
||||
CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {}
|
||||
CheckEvent::Msg(Message::Unknown) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -244,10 +271,16 @@ impl CheckWatcherState {
|
|||
/// have to wrap sub-processes output handling in a thread and pass messages
|
||||
/// back over a channel.
|
||||
struct WatchThread {
|
||||
message_recv: Receiver<cargo_metadata::Message>,
|
||||
message_recv: Receiver<CheckEvent>,
|
||||
cancel_send: Sender<()>,
|
||||
}
|
||||
|
||||
enum CheckEvent {
|
||||
Begin,
|
||||
Msg(cargo_metadata::Message),
|
||||
End,
|
||||
}
|
||||
|
||||
impl WatchThread {
|
||||
fn new(
|
||||
check_command: Option<&String>,
|
||||
|
@ -273,6 +306,7 @@ impl WatchThread {
|
|||
.spawn()
|
||||
.expect("couldn't launch cargo");
|
||||
|
||||
message_send.send(CheckEvent::Begin).unwrap();
|
||||
for message in cargo_metadata::parse_messages(command.stdout.take().unwrap()) {
|
||||
match cancel_recv.try_recv() {
|
||||
Ok(()) | Err(TryRecvError::Disconnected) => {
|
||||
|
@ -281,8 +315,9 @@ impl WatchThread {
|
|||
Err(TryRecvError::Empty) => (),
|
||||
}
|
||||
|
||||
message_send.send(message.unwrap()).unwrap();
|
||||
message_send.send(CheckEvent::Msg(message.unwrap())).unwrap();
|
||||
}
|
||||
message_send.send(CheckEvent::End).unwrap();
|
||||
});
|
||||
WatchThread { message_recv, cancel_send }
|
||||
}
|
||||
|
|
|
@ -338,6 +338,14 @@ fn loop_turn(
|
|||
task_sender.send(Task::Notify(not)).unwrap();
|
||||
}
|
||||
}
|
||||
CheckTask::Status(progress) => {
|
||||
let params = req::ProgressParams {
|
||||
token: req::ProgressToken::String("rustAnalyzer/cargoWatcher".to_string()),
|
||||
value: req::ProgressParamsValue::WorkDone(progress),
|
||||
};
|
||||
let not = notification_new::<req::Progress>(params);
|
||||
task_sender.send(Task::Notify(not)).unwrap();
|
||||
}
|
||||
},
|
||||
Event::Msg(msg) => match msg {
|
||||
Message::Request(req) => on_request(
|
||||
|
|
|
@ -57,7 +57,50 @@ export class StatusDisplay implements vscode.Disposable {
|
|||
this.statusBarItem.dispose();
|
||||
}
|
||||
|
||||
public handleProgressNotification(params: ProgressParams) {
|
||||
const { token, value } = params;
|
||||
if (token !== "rustAnalyzer/cargoWatcher") {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Got progress notification", token, value)
|
||||
switch (value.kind) {
|
||||
case "begin":
|
||||
this.show();
|
||||
break;
|
||||
|
||||
case "report":
|
||||
if (value.message) {
|
||||
this.packageName = value.message;
|
||||
}
|
||||
break;
|
||||
|
||||
case "end":
|
||||
this.hide();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private frame() {
|
||||
return spinnerFrames[(this.i = ++this.i % spinnerFrames.length)];
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Replace this once vscode-languageclient is updated to LSP 3.15
|
||||
interface ProgressParams {
|
||||
token: string
|
||||
value: WorkDoneProgress
|
||||
}
|
||||
|
||||
enum WorkDoneProgressKind {
|
||||
Begin = "begin",
|
||||
Report = "report",
|
||||
End = "end"
|
||||
}
|
||||
|
||||
interface WorkDoneProgress {
|
||||
kind: WorkDoneProgressKind,
|
||||
message?: string
|
||||
cancelable?: boolean
|
||||
percentage?: string
|
||||
}
|
|
@ -8,6 +8,7 @@ import { SyntaxTreeContentProvider } from './commands/syntaxTree';
|
|||
import * as events from './events';
|
||||
import * as notifications from './notifications';
|
||||
import { Server } from './server';
|
||||
import { StatusDisplay } from './commands/watch_status';
|
||||
|
||||
export async function activate(context: vscode.ExtensionContext) {
|
||||
function disposeOnDeactivation(disposable: vscode.Disposable) {
|
||||
|
@ -83,6 +84,9 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
overrideCommand('type', commands.onEnter.handle);
|
||||
}
|
||||
|
||||
const watchStatus = new StatusDisplay(Server.config.cargoCheckOptions.command || 'check');
|
||||
disposeOnDeactivation(watchStatus);
|
||||
|
||||
// Notifications are events triggered by the language server
|
||||
const allNotifications: Iterable<[
|
||||
string,
|
||||
|
@ -92,6 +96,10 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
'rust-analyzer/publishDecorations',
|
||||
notifications.publishDecorations.handle,
|
||||
],
|
||||
[
|
||||
'$/progress',
|
||||
(params) => watchStatus.handleProgressNotification(params),
|
||||
]
|
||||
];
|
||||
const syntaxTreeContentProvider = new SyntaxTreeContentProvider();
|
||||
const expandMacroContentProvider = new ExpandMacroContentProvider();
|
||||
|
|
Loading…
Reference in a new issue