mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +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 crossbeam_channel::{select, unbounded, Receiver, RecvError, Sender, TryRecvError};
|
||||||
use lsp_types::{
|
use lsp_types::{
|
||||||
Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, DiagnosticTag, Location,
|
Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, DiagnosticTag, Location,
|
||||||
NumberOrString, Position, Range, Url,
|
NumberOrString, Position, Range, Url, WorkDoneProgress, WorkDoneProgressBegin,
|
||||||
|
WorkDoneProgressEnd, WorkDoneProgressReport,
|
||||||
};
|
};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -132,6 +133,7 @@ impl CheckWatcherSharedState {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum CheckTask {
|
pub enum CheckTask {
|
||||||
Update(Url),
|
Update(Url),
|
||||||
|
Status(WorkDoneProgress),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum CheckCommand {
|
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 {
|
match msg {
|
||||||
Message::CompilerArtifact(_msg) => {
|
CheckEvent::Begin => {
|
||||||
// TODO: Status display
|
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 =
|
let map_result =
|
||||||
match map_rust_diagnostic_to_lsp(&msg.message, &self.workspace_root) {
|
match map_rust_diagnostic_to_lsp(&msg.message, &self.workspace_root) {
|
||||||
Some(map_result) => map_result,
|
Some(map_result) => map_result,
|
||||||
|
@ -232,8 +259,8 @@ impl CheckWatcherState {
|
||||||
task_send.send(CheckTask::Update(location.uri)).unwrap();
|
task_send.send(CheckTask::Update(location.uri)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::BuildScriptExecuted(_msg) => {}
|
CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {}
|
||||||
Message::Unknown => {}
|
CheckEvent::Msg(Message::Unknown) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,10 +271,16 @@ impl CheckWatcherState {
|
||||||
/// have to wrap sub-processes output handling in a thread and pass messages
|
/// have to wrap sub-processes output handling in a thread and pass messages
|
||||||
/// back over a channel.
|
/// back over a channel.
|
||||||
struct WatchThread {
|
struct WatchThread {
|
||||||
message_recv: Receiver<cargo_metadata::Message>,
|
message_recv: Receiver<CheckEvent>,
|
||||||
cancel_send: Sender<()>,
|
cancel_send: Sender<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum CheckEvent {
|
||||||
|
Begin,
|
||||||
|
Msg(cargo_metadata::Message),
|
||||||
|
End,
|
||||||
|
}
|
||||||
|
|
||||||
impl WatchThread {
|
impl WatchThread {
|
||||||
fn new(
|
fn new(
|
||||||
check_command: Option<&String>,
|
check_command: Option<&String>,
|
||||||
|
@ -273,6 +306,7 @@ impl WatchThread {
|
||||||
.spawn()
|
.spawn()
|
||||||
.expect("couldn't launch cargo");
|
.expect("couldn't launch cargo");
|
||||||
|
|
||||||
|
message_send.send(CheckEvent::Begin).unwrap();
|
||||||
for message in cargo_metadata::parse_messages(command.stdout.take().unwrap()) {
|
for message in cargo_metadata::parse_messages(command.stdout.take().unwrap()) {
|
||||||
match cancel_recv.try_recv() {
|
match cancel_recv.try_recv() {
|
||||||
Ok(()) | Err(TryRecvError::Disconnected) => {
|
Ok(()) | Err(TryRecvError::Disconnected) => {
|
||||||
|
@ -281,8 +315,9 @@ impl WatchThread {
|
||||||
Err(TryRecvError::Empty) => (),
|
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 }
|
WatchThread { message_recv, cancel_send }
|
||||||
}
|
}
|
||||||
|
|
|
@ -338,6 +338,14 @@ fn loop_turn(
|
||||||
task_sender.send(Task::Notify(not)).unwrap();
|
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 {
|
Event::Msg(msg) => match msg {
|
||||||
Message::Request(req) => on_request(
|
Message::Request(req) => on_request(
|
||||||
|
|
|
@ -57,7 +57,50 @@ export class StatusDisplay implements vscode.Disposable {
|
||||||
this.statusBarItem.dispose();
|
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() {
|
private frame() {
|
||||||
return spinnerFrames[(this.i = ++this.i % spinnerFrames.length)];
|
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 events from './events';
|
||||||
import * as notifications from './notifications';
|
import * as notifications from './notifications';
|
||||||
import { Server } from './server';
|
import { Server } from './server';
|
||||||
|
import { StatusDisplay } from './commands/watch_status';
|
||||||
|
|
||||||
export async function activate(context: vscode.ExtensionContext) {
|
export async function activate(context: vscode.ExtensionContext) {
|
||||||
function disposeOnDeactivation(disposable: vscode.Disposable) {
|
function disposeOnDeactivation(disposable: vscode.Disposable) {
|
||||||
|
@ -83,6 +84,9 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||||
overrideCommand('type', commands.onEnter.handle);
|
overrideCommand('type', commands.onEnter.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const watchStatus = new StatusDisplay(Server.config.cargoCheckOptions.command || 'check');
|
||||||
|
disposeOnDeactivation(watchStatus);
|
||||||
|
|
||||||
// Notifications are events triggered by the language server
|
// Notifications are events triggered by the language server
|
||||||
const allNotifications: Iterable<[
|
const allNotifications: Iterable<[
|
||||||
string,
|
string,
|
||||||
|
@ -92,6 +96,10 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||||
'rust-analyzer/publishDecorations',
|
'rust-analyzer/publishDecorations',
|
||||||
notifications.publishDecorations.handle,
|
notifications.publishDecorations.handle,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'$/progress',
|
||||||
|
(params) => watchStatus.handleProgressNotification(params),
|
||||||
|
]
|
||||||
];
|
];
|
||||||
const syntaxTreeContentProvider = new SyntaxTreeContentProvider();
|
const syntaxTreeContentProvider = new SyntaxTreeContentProvider();
|
||||||
const expandMacroContentProvider = new ExpandMacroContentProvider();
|
const expandMacroContentProvider = new ExpandMacroContentProvider();
|
||||||
|
|
Loading…
Reference in a new issue