toolkit for mdBook [mirror of my GitHub repo] docs.tonywu.dev/mdbookkit/
permalinks rust-analyzer mdbook
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix(rustdoc-links): display more rust-analyzer progress updates

Tony Wu 643745df 3410b876

+75 -37
+52 -18
crates/mdbook-rustdoc-links/src/client.rs
··· 3 3 ops::ControlFlow, 4 4 process::Stdio, 5 5 sync::{Arc, RwLock}, 6 - task::Poll, 7 6 time::Duration, 8 7 }; 9 8 ··· 16 15 InitializeResult, InitializedParams, LogMessageParams, MessageType, NumberOrString, Position, 17 16 PositionEncodingKind, ProgressParams, ProgressParamsValue, ServerInfo, ShowMessageParams, 18 17 TextDocumentIdentifier, TextDocumentItem, TextDocumentPositionParams, Url, 19 - WindowClientCapabilities, WorkDoneProgress, WorkspaceFolder, 18 + WindowClientCapabilities, WorkDoneProgress, WorkDoneProgressBegin, WorkDoneProgressEnd, 19 + WorkDoneProgressReport, WorkspaceFolder, 20 20 notification::{LogMessage, Progress, PublishDiagnostics, ShowMessage}, 21 21 request::Request, 22 22 }; ··· 33 33 34 34 use mdbookkit::{ 35 35 emit_debug, 36 + env::is_logging, 36 37 error::{ExpectLock, FutureWithError}, 38 + logging::styled, 37 39 ticker, ticker_event, 38 40 url::UrlToPath, 39 41 }; ··· 41 43 use crate::{ 42 44 env::Environment, 43 45 link::ItemLinks, 44 - sync::{Debounce, Debouncing}, 46 + sync::{Debounce, DebounceUpdate, Debouncing}, 45 47 }; 46 48 47 49 /// LSP client to talk to rust-analyzer. ··· 125 127 #[instrument("spawn_lsp", level = "debug", skip_all)] 126 128 async fn spawn(env: &Environment) -> Result<Self> { 127 129 struct State { 128 - sender: mpsc::Sender<Poll<()>>, 130 + sender: mpsc::Sender<DebounceUpdate<()>>, 129 131 ticker: Option<tracing::Span>, 130 132 // this span is never entered, ticker/timing is updated on span close 131 133 percent_indexed: Option<u32>, ··· 177 179 #[instrument(level = "trace", skip(state))] 178 180 fn probe_progress(state: &mut State, progress: ProgressParams) { 179 181 match indexing_progress(&progress) { 180 - Some(WorkDoneProgress::Begin(begin)) => { 182 + Some(IndexingProgress::CachePriming(WorkDoneProgress::Begin(begin))) => { 181 183 state.percent_indexed = Some(0); 182 184 183 185 let msg = begin.message.as_deref().unwrap_or_default(); 184 186 ticker_event!(state.ticker(), Level::INFO, "{msg}"); 185 187 186 188 let tx = state.sender.clone(); 187 - tokio::spawn(async move { tx.send(Poll::Pending).await.ok() }); 189 + tokio::spawn(async move { tx.send(DebounceUpdate::Reset).await.ok() }); 188 190 } 189 191 190 - Some(WorkDoneProgress::Report(report)) => { 192 + Some(IndexingProgress::CachePriming(WorkDoneProgress::Report(report))) => { 191 193 if let Some(msg) = report.message.as_deref() 192 194 && (state.last_update.as_deref()) 193 195 .map(|last| last != msg) ··· 226 228 } 227 229 } 228 230 229 - Some(WorkDoneProgress::End(_)) => { 231 + Some(IndexingProgress::CachePriming(WorkDoneProgress::End(_))) => { 230 232 let Some(indexed) = state.percent_indexed else { 231 233 trace!("progress was considered spurious"); 232 234 return; ··· 241 243 state.ticker.take(); 242 244 243 245 let tx = state.sender.clone(); 244 - tokio::spawn(async move { tx.send(Poll::Ready(())).await.ok() }); 246 + tokio::spawn(async move { tx.send(DebounceUpdate::Ready(())).await.ok() }); 245 247 } 246 248 247 - None => { 248 - trace!("ignoring unsupported workDoneProgress") 249 + Some(IndexingProgress::Other(message)) => { 250 + if let Some(ticker) = state.ticker() { 251 + if is_logging() { 252 + ticker_event!(ticker, Level::DEBUG, "{message}"); 253 + } else { 254 + ticker_event!(ticker, Level::INFO, "{}", styled(message).dim()); 255 + } 256 + let tx = state.sender.clone(); 257 + tokio::spawn(async move { tx.send(DebounceUpdate::Alive).await.ok() }); 258 + } 249 259 } 260 + 261 + None => {} 250 262 } 251 263 } 252 264 ··· 567 579 } 568 580 } 569 581 570 - fn indexing_progress(progress: &ProgressParams) -> Option<&WorkDoneProgress> { 582 + enum IndexingProgress<'a> { 583 + CachePriming(&'a WorkDoneProgress), 584 + Other(&'a String), 585 + } 586 + 587 + fn indexing_progress(progress: &ProgressParams) -> Option<IndexingProgress<'_>> { 571 588 match progress { 572 589 ProgressParams { 573 590 token: NumberOrString::String(token), 574 591 value: ProgressParamsValue::WorkDone(progress), 575 - } if matches!( 576 - token.as_ref(), 577 - "rustAnalyzer/Indexing" | "rustAnalyzer/cachePriming" 578 - ) => 579 - { 580 - Some(progress) 592 + } => { 593 + if matches!( 594 + token.as_ref(), 595 + "rustAnalyzer/Indexing" | "rustAnalyzer/cachePriming" 596 + ) { 597 + Some(IndexingProgress::CachePriming(progress)) 598 + } else if let WorkDoneProgress::Begin(WorkDoneProgressBegin { 599 + message: Some(message), 600 + .. 601 + }) 602 + | WorkDoneProgress::Report(WorkDoneProgressReport { 603 + message: Some(message), 604 + .. 605 + }) 606 + | WorkDoneProgress::End(WorkDoneProgressEnd { 607 + message: Some(message), 608 + .. 609 + }) = progress 610 + { 611 + Some(IndexingProgress::Other(message)) 612 + } else { 613 + None 614 + } 581 615 } 582 616 _ => None, 583 617 }
+15 -5
crates/mdbook-rustdoc-links/src/sync.rs
··· 1 1 use std::{ 2 2 sync::{Arc, RwLock}, 3 - task::Poll, 4 3 time::Duration, 5 4 }; 6 5 ··· 17 16 pub struct Debouncing<T> { 18 17 pub debounce: Duration, 19 18 pub timeout: Duration, 20 - pub receiver: mpsc::Receiver<Poll<T>>, 19 + pub receiver: mpsc::Receiver<DebounceUpdate<T>>, 20 + } 21 + 22 + pub enum DebounceUpdate<T> { 23 + Reset, 24 + Alive, 25 + Ready(T), 21 26 } 22 27 23 28 impl<T> Debouncing<T> ··· 55 60 } 56 61 57 62 match value { 58 - Ok(Poll::Ready(value)) => { 63 + Ok(DebounceUpdate::Ready(value)) => { 59 64 trace!("state is ready; deferring notification"); 60 65 let event = event.clone(); 61 66 let state = state.clone(); ··· 68 73 })); 69 74 } 70 75 71 - Ok(Poll::Pending) => { 72 - trace!("state is pending"); 76 + Ok(DebounceUpdate::Reset) => { 77 + trace!("state has been reset"); 73 78 *state.write().expect_lock() = State::Pending; 74 79 event.notify_waiters(); 80 + } 81 + 82 + Ok(DebounceUpdate::Alive) => { 83 + trace!("sender is alive"); 84 + // allows rx to not time out 75 85 } 76 86 77 87 Err(_) => {
+2 -1
crates/mdbook-rustdoc-links/src/tests/snaps/docs/src/rustdoc-links/getting-started.md.snap
··· 9 9 You will need to: 10 10 11 11 1. Have [rust-analyzer].: 12 - 13 12 - If you already use the [VS Code extension][ra-extension], no setup is required: the 14 13 preprocessor automatically uses the server binary packaged with it. 15 14 - Otherwise, [install][ra-install] rust-analyzer (e.g. via `rustup`) and make sure it ··· 25 24 releases][gh-releases]. 26 25 27 26 <!-- TODO: cargo binstall --> 27 + 28 + {{#include ../snippets/mdbook-0.4.md}} 28 29 29 30 ## Configure 30 31
+1 -1
crates/mdbook-rustdoc-links/src/tests/snaps/docs/src/rustdoc-links/getting-started.md.stderr.snap
··· 3 3 expression: report 4 4 --- 5 5 info: link resolved 6 - ╭─[docs/src/rustdoc-links/getting-started.md:55:6] 6 + ╭─[docs/src/rustdoc-links/getting-started.md:56:6] 7 7 8 8 │ Like [`std::thread::spawn`], [`tokio::task::spawn`] returns a 9 9 · ───────────┬────────── ───────────┬──────────
+1 -1
crates/mdbook-rustdoc-links/src/tests/snaps/docs/src/rustdoc-links/index.md.snap
··· 52 52 - [Supported syntax](supported-syntax.md): Full list of link syntax with examples. Know 53 53 how to link to additional items such as 54 54 [functions, macros](supported-syntax.md#functions-and-macros), and 55 - [implementors](supported-syntax.md#implementors-and-fully-qualified-syntax). 55 + [implementors](supported-syntax.md#fully-qualified-paths). 56 56 57 57 - [Name resolution](name-resolution.md): Understand how the preprocessor finds Rust 58 58 items, including
+4 -11
crates/mdbook-rustdoc-links/tests/env.rs
··· 24 24 25 25 info!("setup: compile self"); 26 26 Command::new("cargo") 27 - .args([ 28 - "build", 29 - "--package", 30 - env!("CARGO_PKG_NAME"), 31 - "--all-features", 32 - "--bin", 33 - "mdbook-rustdoc-link", 34 - ]) 27 + .args(["build", "--package", env!("CARGO_PKG_NAME")]) 35 28 .arg(if cfg!(debug_assertions) { 36 29 "--profile=dev" 37 30 } else { ··· 59 52 std::fs::File::options() 60 53 .append(true) 61 54 .open(root.path().join("book.toml"))? 62 - .pipe(|mut file| file.write_all("[preprocessor.rustdoc-link]\n".as_bytes()))?; 55 + .pipe(|mut file| file.write_all("[preprocessor.rustdoc-links]\n".as_bytes()))?; 63 56 64 57 info!("when: book is not a Cargo project"); 65 58 info!("then: preprocessor fails"); ··· 70 63 .assert() 71 64 .failure() 72 65 .stderr(predicate::str::contains( 73 - "failed to determine the current Cargo project", 66 + "Failed to determine the current Cargo project", 74 67 )); 75 68 76 69 info!("given: book is a Cargo project"); ··· 82 75 .assert() 83 76 .success(); 84 77 85 - if Command::new("mdbook-rustdoc-link") 78 + if Command::new("mdbook-rustdoc-links") 86 79 .arg("rust-analyzer") 87 80 .env("PATH", &path) 88 81 .current_dir(&root)