Auto merge of #16704 - Veykril:stuff, r=Veykril

internal: Simplify
This commit is contained in:
bors 2024-03-02 09:37:26 +00:00
commit 5c4c126832
11 changed files with 122 additions and 125 deletions

View file

@ -494,7 +494,7 @@ impl CommandHandle {
let (sender, receiver) = unbounded(); let (sender, receiver) = unbounded();
let actor = CargoActor::new(sender, stdout, stderr); let actor = CargoActor::new(sender, stdout, stderr);
let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
.name("CargoHandle".to_owned()) .name("CommandHandle".to_owned())
.spawn(move || actor.run()) .spawn(move || actor.run())
.expect("failed to spawn thread"); .expect("failed to spawn thread");
Ok(CommandHandle { program, arguments, current_dir, child, thread, receiver }) Ok(CommandHandle { program, arguments, current_dir, child, thread, receiver })

View file

@ -1,4 +1,4 @@
use hir::{self, HasVisibility}; use hir::HasVisibility;
use ide_db::{ use ide_db::{
assists::{AssistId, AssistKind}, assists::{AssistId, AssistKind},
defs::Definition, defs::Definition,

View file

@ -82,6 +82,7 @@ pub fn parallel_prime_caches(
stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
.allow_leak(true) .allow_leak(true)
.name("PrimeCaches".to_owned())
.spawn(move || Cancelled::catch(|| worker(db))) .spawn(move || Cancelled::catch(|| worker(db)))
.expect("failed to spawn thread"); .expect("failed to spawn thread");
} }

View file

@ -54,33 +54,33 @@ fn spacing_to_external(spacing: Spacing) -> proc_macro::Spacing {
} }
} }
struct LiteralFormatter<S>(bridge::Literal<S, Symbol>); /// Invokes the callback with a `&[&str]` consisting of each part of the
/// literal's representation. This is done to allow the `ToString` and
impl<S> LiteralFormatter<S> { /// `Display` implementations to borrow references to symbol values, and
/// Invokes the callback with a `&[&str]` consisting of each part of the /// both be optimized to reduce overhead.
/// literal's representation. This is done to allow the `ToString` and fn literal_with_stringify_parts<S, R>(
/// `Display` implementations to borrow references to symbol values, and literal: &bridge::Literal<S, Symbol>,
/// both be optimized to reduce overhead. interner: SymbolInternerRef,
fn with_stringify_parts<R>( f: impl FnOnce(&[&str]) -> R,
&self, ) -> R {
interner: SymbolInternerRef, /// Returns a string containing exactly `num` '#' characters.
f: impl FnOnce(&[&str]) -> R, /// Uses a 256-character source string literal which is always safe to
) -> R { /// index with a `u8` index.
/// Returns a string containing exactly `num` '#' characters. fn get_hashes_str(num: u8) -> &'static str {
/// Uses a 256-character source string literal which is always safe to const HASHES: &str = "\
/// index with a `u8` index.
fn get_hashes_str(num: u8) -> &'static str {
const HASHES: &str = "\
################################################################\ ################################################################\
################################################################\ ################################################################\
################################################################\ ################################################################\
################################################################\ ################################################################\
"; ";
const _: () = assert!(HASHES.len() == 256); const _: () = assert!(HASHES.len() == 256);
&HASHES[..num as usize] &HASHES[..num as usize]
} }
self.with_symbol_and_suffix(interner, |symbol, suffix| match self.0.kind { {
let symbol = &*literal.symbol.text(interner);
let suffix = &*literal.suffix.map(|s| s.text(interner)).unwrap_or_default();
match literal.kind {
bridge::LitKind::Byte => f(&["b'", symbol, "'", suffix]), bridge::LitKind::Byte => f(&["b'", symbol, "'", suffix]),
bridge::LitKind::Char => f(&["'", symbol, "'", suffix]), bridge::LitKind::Char => f(&["'", symbol, "'", suffix]),
bridge::LitKind::Str => f(&["\"", symbol, "\"", suffix]), bridge::LitKind::Str => f(&["\"", symbol, "\"", suffix]),
@ -101,16 +101,6 @@ impl<S> LiteralFormatter<S> {
bridge::LitKind::Integer | bridge::LitKind::Float | bridge::LitKind::ErrWithGuar => { bridge::LitKind::Integer | bridge::LitKind::Float | bridge::LitKind::ErrWithGuar => {
f(&[symbol, suffix]) f(&[symbol, suffix])
} }
}) }
}
fn with_symbol_and_suffix<R>(
&self,
interner: SymbolInternerRef,
f: impl FnOnce(&str, &str) -> R,
) -> R {
let symbol = self.0.symbol.text(interner);
let suffix = self.0.suffix.map(|s| s.text(interner)).unwrap_or_default();
f(symbol.as_str(), suffix.as_str())
} }
} }

View file

@ -15,8 +15,8 @@ use proc_macro::bridge::{self, server};
use span::{Span, FIXUP_ERASED_FILE_AST_ID_MARKER}; use span::{Span, FIXUP_ERASED_FILE_AST_ID_MARKER};
use crate::server::{ use crate::server::{
delim_to_external, delim_to_internal, token_stream::TokenStreamBuilder, LiteralFormatter, delim_to_external, delim_to_internal, literal_with_stringify_parts,
Symbol, SymbolInternerRef, SYMBOL_INTERNER, token_stream::TokenStreamBuilder, Symbol, SymbolInternerRef, SYMBOL_INTERNER,
}; };
mod tt { mod tt {
pub use ::tt::*; pub use ::tt::*;
@ -180,12 +180,11 @@ impl server::TokenStream for RaSpanServer {
} }
bridge::TokenTree::Literal(literal) => { bridge::TokenTree::Literal(literal) => {
let literal = LiteralFormatter(literal); let text = literal_with_stringify_parts(&literal, self.interner, |parts| {
let text = literal.with_stringify_parts(self.interner, |parts| {
::tt::SmolStr::from_iter(parts.iter().copied()) ::tt::SmolStr::from_iter(parts.iter().copied())
}); });
let literal = tt::Literal { text, span: literal.0.span }; let literal = tt::Literal { text, span: literal.span };
let leaf: tt::Leaf = tt::Leaf::from(literal); let leaf: tt::Leaf = tt::Leaf::from(literal);
let tree = tt::TokenTree::from(leaf); let tree = tt::TokenTree::from(leaf);
Self::TokenStream::from_iter(iter::once(tree)) Self::TokenStream::from_iter(iter::once(tree))
@ -251,10 +250,17 @@ impl server::TokenStream for RaSpanServer {
.into_iter() .into_iter()
.map(|tree| match tree { .map(|tree| match tree {
tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
bridge::TokenTree::Ident(bridge::Ident { bridge::TokenTree::Ident(match ident.text.strip_prefix("r#") {
sym: Symbol::intern(self.interner, ident.text.trim_start_matches("r#")), Some(text) => bridge::Ident {
is_raw: ident.text.starts_with("r#"), sym: Symbol::intern(self.interner, text),
span: ident.span, is_raw: true,
span: ident.span,
},
None => bridge::Ident {
sym: Symbol::intern(self.interner, &ident.text),
is_raw: false,
span: ident.span,
},
}) })
} }
tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => { tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => {
@ -285,11 +291,12 @@ impl server::TokenStream for RaSpanServer {
} }
impl server::SourceFile for RaSpanServer { impl server::SourceFile for RaSpanServer {
// FIXME these are all stubs
fn eq(&mut self, _file1: &Self::SourceFile, _file2: &Self::SourceFile) -> bool { fn eq(&mut self, _file1: &Self::SourceFile, _file2: &Self::SourceFile) -> bool {
// FIXME
true true
} }
fn path(&mut self, _file: &Self::SourceFile) -> String { fn path(&mut self, _file: &Self::SourceFile) -> String {
// FIXME
String::new() String::new()
} }
fn is_real(&mut self, _file: &Self::SourceFile) -> bool { fn is_real(&mut self, _file: &Self::SourceFile) -> bool {
@ -306,11 +313,15 @@ impl server::Span for RaSpanServer {
SourceFile {} SourceFile {}
} }
fn save_span(&mut self, _span: Self::Span) -> usize { fn save_span(&mut self, _span: Self::Span) -> usize {
// FIXME stub, requires builtin quote! implementation // FIXME, quote is incompatible with third-party tools
// This is called by the quote proc-macro which is expanded when the proc-macro is compiled
// As such, r-a will never observe this
0 0
} }
fn recover_proc_macro_span(&mut self, _id: usize) -> Self::Span { fn recover_proc_macro_span(&mut self, _id: usize) -> Self::Span {
// FIXME stub, requires builtin quote! implementation // FIXME, quote is incompatible with third-party tools
// This is called by the expansion of quote!, r-a will observe this, but we don't have
// access to the spans that were encoded
self.call_site self.call_site
} }
/// Recent feature, not yet in the proc_macro /// Recent feature, not yet in the proc_macro

View file

@ -8,8 +8,8 @@ use std::{
use proc_macro::bridge::{self, server}; use proc_macro::bridge::{self, server};
use crate::server::{ use crate::server::{
delim_to_external, delim_to_internal, token_stream::TokenStreamBuilder, LiteralFormatter, delim_to_external, delim_to_internal, literal_with_stringify_parts,
Symbol, SymbolInternerRef, SYMBOL_INTERNER, token_stream::TokenStreamBuilder, Symbol, SymbolInternerRef, SYMBOL_INTERNER,
}; };
mod tt { mod tt {
pub use proc_macro_api::msg::TokenId; pub use proc_macro_api::msg::TokenId;
@ -171,12 +171,12 @@ impl server::TokenStream for TokenIdServer {
} }
bridge::TokenTree::Literal(literal) => { bridge::TokenTree::Literal(literal) => {
let literal = LiteralFormatter(literal); let text = literal_with_stringify_parts(&literal, self.interner, |parts| {
let text = literal.with_stringify_parts(self.interner, |parts| {
::tt::SmolStr::from_iter(parts.iter().copied()) ::tt::SmolStr::from_iter(parts.iter().copied())
}); });
let literal = tt::Literal { text, span: literal.0.span }; let literal = tt::Literal { text, span: literal.span };
let leaf = tt::Leaf::from(literal); let leaf = tt::Leaf::from(literal);
let tree = TokenTree::from(leaf); let tree = TokenTree::from(leaf);
Self::TokenStream::from_iter(iter::once(tree)) Self::TokenStream::from_iter(iter::once(tree))

View file

@ -152,6 +152,13 @@ config_data! {
// FIXME(@poliorcetics): move to multiple targets here too, but this will need more work // FIXME(@poliorcetics): move to multiple targets here too, but this will need more work
// than `checkOnSave_target` // than `checkOnSave_target`
cargo_target: Option<String> = "null", cargo_target: Option<String> = "null",
/// Optional path to a rust-analyzer specific target directory.
/// This prevents rust-analyzer's `cargo check` and initial build-script and proc-macro
/// building from locking the `Cargo.lock` at the expense of duplicating build artifacts.
///
/// Set to `true` to use a subdirectory of the existing target directory or
/// set to a path relative to the workspace to use that path.
cargo_targetDir | rust_analyzerTargetDir: Option<TargetDirectory> = "null",
/// Unsets the implicit `#[cfg(test)]` for the specified crates. /// Unsets the implicit `#[cfg(test)]` for the specified crates.
cargo_unsetTest: Vec<String> = "[\"core\"]", cargo_unsetTest: Vec<String> = "[\"core\"]",
@ -518,14 +525,6 @@ config_data! {
/// tests or binaries. For example, it may be `--release`. /// tests or binaries. For example, it may be `--release`.
runnables_extraArgs: Vec<String> = "[]", runnables_extraArgs: Vec<String> = "[]",
/// Optional path to a rust-analyzer specific target directory.
/// This prevents rust-analyzer's `cargo check` from locking the `Cargo.lock`
/// at the expense of duplicating build artifacts.
///
/// Set to `true` to use a subdirectory of the existing target directory or
/// set to a path relative to the workspace to use that path.
rust_analyzerTargetDir: Option<TargetDirectory> = "null",
/// Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private /// Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private
/// projects, or "discover" to try to automatically find it if the `rustc-dev` component /// projects, or "discover" to try to automatically find it if the `rustc-dev` component
/// is installed. /// is installed.
@ -1401,14 +1400,12 @@ impl Config {
} }
} }
// FIXME: This should be an AbsolutePathBuf
fn target_dir_from_config(&self) -> Option<PathBuf> { fn target_dir_from_config(&self) -> Option<PathBuf> {
self.data.rust_analyzerTargetDir.as_ref().and_then(|target_dir| match target_dir { self.data.cargo_targetDir.as_ref().and_then(|target_dir| match target_dir {
TargetDirectory::UseSubdirectory(yes) if *yes => { TargetDirectory::UseSubdirectory(true) => Some(PathBuf::from("target/rust-analyzer")),
Some(PathBuf::from("target/rust-analyzer")) TargetDirectory::UseSubdirectory(false) => None,
} TargetDirectory::Directory(dir) if dir.is_relative() => Some(dir.clone()),
TargetDirectory::UseSubdirectory(_) => None, TargetDirectory::Directory(_) => None,
TargetDirectory::Directory(dir) => Some(dir.clone()),
}) })
} }
@ -2745,7 +2742,7 @@ mod tests {
"rust": { "analyzerTargetDir": null } "rust": { "analyzerTargetDir": null }
})) }))
.unwrap(); .unwrap();
assert_eq!(config.data.rust_analyzerTargetDir, None); assert_eq!(config.data.cargo_targetDir, None);
assert!( assert!(
matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir.is_none()) matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir.is_none())
); );
@ -2764,10 +2761,7 @@ mod tests {
"rust": { "analyzerTargetDir": true } "rust": { "analyzerTargetDir": true }
})) }))
.unwrap(); .unwrap();
assert_eq!( assert_eq!(config.data.cargo_targetDir, Some(TargetDirectory::UseSubdirectory(true)));
config.data.rust_analyzerTargetDir,
Some(TargetDirectory::UseSubdirectory(true))
);
assert!( assert!(
matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(PathBuf::from("target/rust-analyzer"))) matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(PathBuf::from("target/rust-analyzer")))
); );
@ -2787,7 +2781,7 @@ mod tests {
})) }))
.unwrap(); .unwrap();
assert_eq!( assert_eq!(
config.data.rust_analyzerTargetDir, config.data.cargo_targetDir,
Some(TargetDirectory::Directory(PathBuf::from("other_folder"))) Some(TargetDirectory::Directory(PathBuf::from("other_folder")))
); );
assert!( assert!(

View file

@ -90,18 +90,13 @@ pub(crate) fn handle_did_change_text_document(
let _p = tracing::span!(tracing::Level::INFO, "handle_did_change_text_document").entered(); let _p = tracing::span!(tracing::Level::INFO, "handle_did_change_text_document").entered();
if let Ok(path) = from_proto::vfs_path(&params.text_document.uri) { if let Ok(path) = from_proto::vfs_path(&params.text_document.uri) {
let data = match state.mem_docs.get_mut(&path) { let Some(DocumentData { version, data }) = state.mem_docs.get_mut(&path) else {
Some(doc) => { tracing::error!(?path, "unexpected DidChangeTextDocument");
// The version passed in DidChangeTextDocument is the version after all edits are applied return Ok(());
// so we should apply it before the vfs is notified.
doc.version = params.text_document.version;
&mut doc.data
}
None => {
tracing::error!("unexpected DidChangeTextDocument: {}", path);
return Ok(());
}
}; };
// The version passed in DidChangeTextDocument is the version after all edits are applied
// so we should apply it before the vfs is notified.
*version = params.text_document.version;
let new_contents = apply_document_changes( let new_contents = apply_document_changes(
state.config.position_encoding(), state.config.position_encoding(),

View file

@ -144,6 +144,16 @@ This option does not take effect until rust-analyzer is restarted.
-- --
Compilation target override (target triple). Compilation target override (target triple).
-- --
[[rust-analyzer.cargo.targetDir]]rust-analyzer.cargo.targetDir (default: `null`)::
+
--
Optional path to a rust-analyzer specific target directory.
This prevents rust-analyzer's `cargo check` and initial build-script and proc-macro
building from locking the `Cargo.lock` at the expense of duplicating build artifacts.
Set to `true` to use a subdirectory of the existing target directory or
set to a path relative to the workspace to use that path.
--
[[rust-analyzer.cargo.unsetTest]]rust-analyzer.cargo.unsetTest (default: `["core"]`):: [[rust-analyzer.cargo.unsetTest]]rust-analyzer.cargo.unsetTest (default: `["core"]`)::
+ +
-- --
@ -814,16 +824,6 @@ Command to be executed instead of 'cargo' for runnables.
Additional arguments to be passed to cargo for runnables such as Additional arguments to be passed to cargo for runnables such as
tests or binaries. For example, it may be `--release`. tests or binaries. For example, it may be `--release`.
-- --
[[rust-analyzer.rust.analyzerTargetDir]]rust-analyzer.rust.analyzerTargetDir (default: `null`)::
+
--
Optional path to a rust-analyzer specific target directory.
This prevents rust-analyzer's `cargo check` from locking the `Cargo.lock`
at the expense of duplicating build artifacts.
Set to `true` to use a subdirectory of the existing target directory or
set to a path relative to the workspace to use that path.
--
[[rust-analyzer.rustc.source]]rust-analyzer.rustc.source (default: `null`):: [[rust-analyzer.rustc.source]]rust-analyzer.rustc.source (default: `null`)::
+ +
-- --

View file

@ -671,6 +671,21 @@
"string" "string"
] ]
}, },
"rust-analyzer.cargo.targetDir": {
"markdownDescription": "Optional path to a rust-analyzer specific target directory.\nThis prevents rust-analyzer's `cargo check` and initial build-script and proc-macro\nbuilding from locking the `Cargo.lock` at the expense of duplicating build artifacts.\n\nSet to `true` to use a subdirectory of the existing target directory or\nset to a path relative to the workspace to use that path.",
"default": null,
"anyOf": [
{
"type": "null"
},
{
"type": "boolean"
},
{
"type": "string"
}
]
},
"rust-analyzer.cargo.unsetTest": { "rust-analyzer.cargo.unsetTest": {
"markdownDescription": "Unsets the implicit `#[cfg(test)]` for the specified crates.", "markdownDescription": "Unsets the implicit `#[cfg(test)]` for the specified crates.",
"default": [ "default": [
@ -1543,21 +1558,6 @@
"type": "string" "type": "string"
} }
}, },
"rust-analyzer.rust.analyzerTargetDir": {
"markdownDescription": "Optional path to a rust-analyzer specific target directory.\nThis prevents rust-analyzer's `cargo check` from locking the `Cargo.lock`\nat the expense of duplicating build artifacts.\n\nSet to `true` to use a subdirectory of the existing target directory or\nset to a path relative to the workspace to use that path.",
"default": null,
"anyOf": [
{
"type": "null"
},
{
"type": "boolean"
},
{
"type": "string"
}
]
},
"rust-analyzer.rustc.source": { "rust-analyzer.rustc.source": {
"markdownDescription": "Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private\nprojects, or \"discover\" to try to automatically find it if the `rustc-dev` component\nis installed.\n\nAny project which uses rust-analyzer with the rustcPrivate\ncrates must set `[package.metadata.rust-analyzer] rustc_private=true` to use it.\n\nThis option does not take effect until rust-analyzer is restarted.", "markdownDescription": "Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private\nprojects, or \"discover\" to try to automatically find it if the `rustc-dev` component\nis installed.\n\nAny project which uses rust-analyzer with the rustcPrivate\ncrates must set `[package.metadata.rust-analyzer] rustc_private=true` to use it.\n\nThis option does not take effect until rust-analyzer is restarted.",
"default": null, "default": null,

View file

@ -12,27 +12,33 @@ use crate::Message;
/// Creates an LSP connection via stdio. /// Creates an LSP connection via stdio.
pub(crate) fn stdio_transport() -> (Sender<Message>, Receiver<Message>, IoThreads) { pub(crate) fn stdio_transport() -> (Sender<Message>, Receiver<Message>, IoThreads) {
let (writer_sender, writer_receiver) = bounded::<Message>(0); let (writer_sender, writer_receiver) = bounded::<Message>(0);
let writer = thread::spawn(move || { let writer = thread::Builder::new()
let stdout = stdout(); .name("LspServerWriter".to_owned())
let mut stdout = stdout.lock(); .spawn(move || {
writer_receiver.into_iter().try_for_each(|it| it.write(&mut stdout)) let stdout = stdout();
}); let mut stdout = stdout.lock();
writer_receiver.into_iter().try_for_each(|it| it.write(&mut stdout))
})
.unwrap();
let (reader_sender, reader_receiver) = bounded::<Message>(0); let (reader_sender, reader_receiver) = bounded::<Message>(0);
let reader = thread::spawn(move || { let reader = thread::Builder::new()
let stdin = stdin(); .name("LspServerReader".to_owned())
let mut stdin = stdin.lock(); .spawn(move || {
while let Some(msg) = Message::read(&mut stdin)? { let stdin = stdin();
let is_exit = matches!(&msg, Message::Notification(n) if n.is_exit()); let mut stdin = stdin.lock();
while let Some(msg) = Message::read(&mut stdin)? {
let is_exit = matches!(&msg, Message::Notification(n) if n.is_exit());
debug!("sending message {:#?}", msg); debug!("sending message {:#?}", msg);
reader_sender.send(msg).expect("receiver was dropped, failed to send a message"); reader_sender.send(msg).expect("receiver was dropped, failed to send a message");
if is_exit { if is_exit {
break; break;
}
} }
} Ok(())
Ok(()) })
}); .unwrap();
let threads = IoThreads { reader, writer }; let threads = IoThreads { reader, writer };
(writer_sender, reader_receiver, threads) (writer_sender, reader_receiver, threads)
} }