diff --git a/Cargo.lock b/Cargo.lock index f3bd3d6b76bd..faefc3b3af4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -865,7 +865,9 @@ dependencies = [ [[package]] name = "lsp-server" -version = "0.6.0" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c351c75989da23b355226dc188dc2b52538a7f4f218d70fd7393c6b62b110444" dependencies = [ "crossbeam-channel", "log", @@ -2041,18 +2043,18 @@ checksum = "45d11d5fc2a97287eded8b170ca80533b3c42646dd7fa386a5eb045817921022" [[package]] name = "xshell" -version = "0.2.1" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4884417669886d3abff14feec797179526ade713f212e54ec08b19bc6bdc86aa" +checksum = "eaad2035244c56da05573d4d7fda5f903c60a5f35b9110e157a14a1df45a9f14" dependencies = [ "xshell-macros", ] [[package]] name = "xshell-macros" -version = "0.2.1" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d92065701c3611323f96eac5475b995421fc7eb2bcba1336cdd80b9b2fb68f" +checksum = "4916a4a3cad759e499a3620523bf9545cc162d7a06163727dde97ce9aaa4cf39" [[package]] name = "xtask" diff --git a/crates/hir-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs index aa09912f302d..a7f68e8214fa 100644 --- a/crates/hir-expand/src/builtin_fn_macro.rs +++ b/crates/hir-expand/src/builtin_fn_macro.rs @@ -532,10 +532,10 @@ fn relative_file( let path = AnchoredPath { anchor: call_site, path: path_str }; let res = db .resolve_path(path) - .ok_or_else(|| ExpandError::Other(format!("failed to load file `{path_str}`").into()))?; + .ok_or_else(|| ExpandError::Other(format!("failed to load file `{}`", path_str).into()))?; // Prevent include itself if res == call_site && !allow_recursion { - Err(ExpandError::Other(format!("recursive inclusion of `{path_str}`").into())) + Err(ExpandError::Other(format!("recursive inclusion of `{}`", path_str).into())) } else { Ok(res) } diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 2609a6079451..5369c6ef7d0c 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -1226,7 +1226,7 @@ impl HirDisplay for Path { .as_ref() .map(|name| name.canonical_name()) .unwrap_or("$crate"); - write!(f, "{name}")? + write!(f, "{}", name)? } } diff --git a/crates/ide-assists/src/handlers/convert_let_else_to_match.rs b/crates/ide-assists/src/handlers/convert_let_else_to_match.rs index 2363aa7cbd90..4c17ffb5a14d 100644 --- a/crates/ide-assists/src/handlers/convert_let_else_to_match.rs +++ b/crates/ide-assists/src/handlers/convert_let_else_to_match.rs @@ -147,7 +147,7 @@ pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext) // remove the mut from the pattern for (b, ismut) in binders.iter() { if *ismut { - pat_no_mut = pat_no_mut.replace(&format!("mut {b}"), &b.to_string()); + pat_no_mut = pat_no_mut.replace(&format!("mut {}", b), &b.to_string()); } } @@ -158,17 +158,17 @@ pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext) }; let replace = if binders.is_empty() { format!( - "match {init_expr} {{ -{indent1}{pat_no_mut} => {binders_str} -{indent1}_ => {branch2} -{indent}}}" + "match {} {{ +{}{} => {} +{}_ => {} +{}}}", init_expr, indent1, pat_no_mut, binders_str, indent1, branch2, indent ) } else { format!( - "let {binders_str_mut} = match {init_expr} {{ -{indent1}{pat_no_mut} => {binders_str}, -{indent1}_ => {branch2} -{indent}}};" + "let {} = match {} {{ +{}{} => {}, +{}_ => {} +{}}};", binders_str_mut, init_expr, indent1, pat_no_mut, binders_str, indent1, branch2, indent ) }; edit.replace(target, replace); diff --git a/crates/ide-assists/src/handlers/generate_documentation_template.rs b/crates/ide-assists/src/handlers/generate_documentation_template.rs index d22d8c831fbe..e6c17c77c3ae 100644 --- a/crates/ide-assists/src/handlers/generate_documentation_template.rs +++ b/crates/ide-assists/src/handlers/generate_documentation_template.rs @@ -214,7 +214,7 @@ fn introduction_builder(ast_func: &ast::Fn, ctx: &AssistContext) -> Option<Strin } else { "" }; - Some(format!("Returns{reference} the {what} of this [`{}`].", linkable_self_ty?)) + Some(format!("Returns{} the {} of this [`{}`].", reference, what, linkable_self_ty?)) } _ => None, }; @@ -228,7 +228,7 @@ fn introduction_builder(ast_func: &ast::Fn, ctx: &AssistContext) -> Option<Strin if what == "len" { what = "length".into() }; - Some(format!("Sets the {what} of this [`{}`].", linkable_self_ty?)) + Some(format!("Sets the {} of this [`{}`].", what, linkable_self_ty?)) }; if let Some(intro) = intro_for_new() { diff --git a/crates/ide-completion/src/completions/fn_param.rs b/crates/ide-completion/src/completions/fn_param.rs index 0cdb8ee11907..320edf45abf4 100644 --- a/crates/ide-completion/src/completions/fn_param.rs +++ b/crates/ide-completion/src/completions/fn_param.rs @@ -46,7 +46,7 @@ pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) ParamKind::Closure(closure) => { let stmt_list = closure.syntax().ancestors().find_map(ast::StmtList::cast)?; params_from_stmt_list_scope(ctx, stmt_list, |name, ty| { - add_new_item_to_acc(&format!("{name}: {ty}")); + add_new_item_to_acc(&format!("{}: {}", name, ty)); }); } } @@ -95,7 +95,7 @@ fn fill_fn_params( if let Some(stmt_list) = function.syntax().parent().and_then(ast::StmtList::cast) { params_from_stmt_list_scope(ctx, stmt_list, |name, ty| { - file_params.entry(format!("{name}: {ty}")).or_insert(name.to_string()); + file_params.entry(format!("{}: {}", name, ty)).or_insert(name.to_string()); }); } remove_duplicated(&mut file_params, param_list.params()); diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index b70d6f9e8dc2..2510dbe82bd9 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -893,7 +893,9 @@ impl<'a> CompletionContext<'a> { it.syntax().text_range().end() == syntax_element.text_range().end() }); - (self.expected_type, self.expected_name) = self.expected_type_and_name(); + let (expected_type, expected_name) = self.expected_type_and_name(); + self.expected_type = expected_type; + self.expected_name = expected_name; // Overwrite the path kind for derives if let Some((original_file, file_with_fake_ident, offset, origin_attr)) = derive_ctx { diff --git a/crates/ide-db/Cargo.toml b/crates/ide-db/Cargo.toml index c5f0cb3c014c..913c4538ac03 100644 --- a/crates/ide-db/Cargo.toml +++ b/crates/ide-db/Cargo.toml @@ -35,5 +35,5 @@ limit = { path = "../limit", version = "0.0.0" } [dev-dependencies] test-utils = { path = "../test-utils" } sourcegen = { path = "../sourcegen" } -xshell = "0.2.1" +xshell = "0.1" expect-test = "1.2.2" diff --git a/crates/ide-db/src/tests/sourcegen_lints.rs b/crates/ide-db/src/tests/sourcegen_lints.rs index b7db1dd8dbc2..61c05c7ffd19 100644 --- a/crates/ide-db/src/tests/sourcegen_lints.rs +++ b/crates/ide-db/src/tests/sourcegen_lints.rs @@ -4,20 +4,16 @@ use std::{borrow::Cow, fs, path::Path}; use itertools::Itertools; use stdx::format_to; use test_utils::project_root; -use xshell::{cmd, Shell}; +use xshell::cmd; /// This clones rustc repo, and so is not worth to keep up-to-date. We update /// manually by un-ignoring the test from time to time. #[test] #[ignore] fn sourcegen_lint_completions() { - let sh = &Shell::new().unwrap(); - let rust_repo = project_root().join("./target/rust"); if !rust_repo.exists() { - cmd!(sh, "git clone --depth=1 https://github.com/rust-lang/rust {rust_repo}") - .run() - .unwrap(); + cmd!("git clone --depth=1 https://github.com/rust-lang/rust {rust_repo}").run().unwrap(); } let mut contents = String::from( @@ -34,19 +30,16 @@ pub struct LintGroup { ", ); - generate_lint_descriptor(sh, &mut contents); + generate_lint_descriptor(&mut contents); contents.push('\n'); generate_feature_descriptor(&mut contents, &rust_repo.join("src/doc/unstable-book/src")); contents.push('\n'); let lints_json = project_root().join("./target/clippy_lints.json"); - cmd!( - sh, - "curl https://rust-lang.github.io/rust-clippy/master/lints.json --output {lints_json}" - ) - .run() - .unwrap(); + cmd!("curl https://rust-lang.github.io/rust-clippy/master/lints.json --output {lints_json}") + .run() + .unwrap(); generate_descriptor_clippy(&mut contents, &lints_json); let contents = sourcegen::add_preamble("sourcegen_lints", sourcegen::reformat(contents)); @@ -55,10 +48,10 @@ pub struct LintGroup { sourcegen::ensure_file_contents(destination.as_path(), &contents); } -fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { +fn generate_lint_descriptor(buf: &mut String) { // FIXME: rustdoc currently requires an input file for -Whelp cc https://github.com/rust-lang/rust/pull/88831 let file = project_root().join(file!()); - let stdout = cmd!(sh, "rustdoc -W help {file}").read().unwrap(); + let stdout = cmd!("rustdoc -W help {file}").read().unwrap(); let start_lints = stdout.find("---- ------- -------").unwrap(); let start_lint_groups = stdout.find("---- ---------").unwrap(); let start_lints_rustdoc = diff --git a/crates/ide-diagnostics/src/handlers/unresolved_module.rs b/crates/ide-diagnostics/src/handlers/unresolved_module.rs index b8f2a9e94a40..3a110eebbd83 100644 --- a/crates/ide-diagnostics/src/handlers/unresolved_module.rs +++ b/crates/ide-diagnostics/src/handlers/unresolved_module.rs @@ -39,7 +39,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedModule) -> Option<Vec< .map(|candidate| { fix( "create_module", - &format!("Create module at `{candidate}`"), + &format!("Create module at `{}`", candidate), FileSystemEdit::CreateFile { dst: AnchoredPathBuf { anchor: d.decl.file_id.original_file(ctx.sema.db), diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index 60fad2d5db2f..42927ad42ce4 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs @@ -424,7 +424,7 @@ fn get_doc_base_url(db: &RootDatabase, def: Definition) -> Option<Url> { | LangCrateOrigin::Std | LangCrateOrigin::Test), ) => { - format!("https://doc.rust-lang.org/nightly/{origin}") + format!("https://doc.rust-lang.org/nightly/{}", origin) } _ => { krate.get_html_root_url(db).or_else(|| { diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index 806f816898bd..02654a5e5daf 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs @@ -168,7 +168,7 @@ fn _format( SyntaxKind::MACRO_TYPE => ("type __ =", ";"), _ => ("", ""), }; - let expansion = format!("{prefix}{expansion}{suffix}"); + let expansion = format!("{}{}{}", prefix, expansion, suffix); let &crate_id = db.relevant_crates(file_id).iter().next()?; let edition = db.crate_graph()[crate_id].edition; diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 116c1c480a1e..e32e42f8ebce 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -379,7 +379,7 @@ fn fn_lifetime_fn_hints( let mut gen_idx_name = { let mut gen = (0u8..).map(|idx| match idx { idx if idx < 10 => SmolStr::from_iter(['\'', (idx + 48) as char]), - idx => format!("'{idx}").into(), + idx => format!("'{}", idx).into(), }); move || gen.next().unwrap_or_default() }; @@ -412,7 +412,7 @@ fn fn_lifetime_fn_hints( Some(it) if config.param_names_for_lifetime_elision_hints => { if let Some(c) = used_names.get_mut(it.text().as_str()) { *c += 1; - SmolStr::from(format!("'{text}{c}", text = it.text().as_str())) + SmolStr::from(format!("'{text}{c}", text = it.text().as_str(), c=c)) } else { used_names.insert(it.text().as_str().into(), 0); SmolStr::from_iter(["\'", it.text().as_str()]) diff --git a/crates/ide/src/moniker.rs b/crates/ide/src/moniker.rs index 6bab9fa1ebbb..70357f280182 100644 --- a/crates/ide/src/moniker.rs +++ b/crates/ide/src/moniker.rs @@ -157,7 +157,7 @@ pub(crate) fn def_to_moniker( LangCrateOrigin::Other => { "https://github.com/rust-lang/rust/library/".into() } - lang => format!("https://github.com/rust-lang/rust/library/{lang}",), + lang => format!("https://github.com/rust-lang/rust/library/{}", lang), }, ), }; diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs index aefb3d059ff3..a0969e20ee3f 100644 --- a/crates/mbe/src/expander/matcher.rs +++ b/crates/mbe/src/expander/matcher.rs @@ -658,7 +658,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { fn match_leaf(lhs: &tt::Leaf, src: &mut TtIter) -> Result<(), ExpandError> { let rhs = src .expect_leaf() - .map_err(|()| ExpandError::binding_error(format!("expected leaf: `{lhs}`")))?; + .map_err(|()| ExpandError::binding_error(format!("expected leaf: `{}`", lhs)))?; match (lhs, rhs) { ( tt::Leaf::Punct(tt::Punct { char: lhs, .. }), diff --git a/crates/mbe/src/expander/transcriber.rs b/crates/mbe/src/expander/transcriber.rs index b1b3f63fd3a5..958266df6f48 100644 --- a/crates/mbe/src/expander/transcriber.rs +++ b/crates/mbe/src/expander/transcriber.rs @@ -21,28 +21,28 @@ impl Bindings { } let mut b: &Binding = - self.inner.get(name).ok_or_else(|| binding_err!("could not find binding `{name}`"))?; + self.inner.get(name).ok_or_else(|| binding_err!("could not find binding `{}`", name))?; for nesting_state in nesting.iter_mut() { nesting_state.hit = true; b = match b { Binding::Fragment(_) => break, Binding::Nested(bs) => bs.get(nesting_state.idx).ok_or_else(|| { nesting_state.at_end = true; - binding_err!("could not find nested binding `{name}`") + binding_err!("could not find nested binding `{}`", name) })?, Binding::Empty => { nesting_state.at_end = true; - return Err(binding_err!("could not find empty binding `{name}`")); + return Err(binding_err!("could not find empty binding `{}`", name)); } }; } match b { Binding::Fragment(it) => Ok(it), Binding::Nested(_) => { - Err(binding_err!("expected simple binding, found nested binding `{name}`")) + Err(binding_err!("expected simple binding, found nested binding `{}`", name)) } Binding::Empty => { - Err(binding_err!("expected simple binding, found empty binding `{name}`")) + Err(binding_err!("expected simple binding, found empty binding `{}`", name)) } } } diff --git a/crates/mbe/src/tt_iter.rs b/crates/mbe/src/tt_iter.rs index fc5590b71845..26b0267023ac 100644 --- a/crates/mbe/src/tt_iter.rs +++ b/crates/mbe/src/tt_iter.rs @@ -106,7 +106,7 @@ impl<'a> TtIter<'a> { } let err = if error || !cursor.is_root() { - Some(ExpandError::binding_error(format!("expected {entry_point:?}"))) + Some(ExpandError::binding_error(format!("expected {:?}", entry_point))) } else { None }; diff --git a/crates/project-model/src/rustc_cfg.rs b/crates/project-model/src/rustc_cfg.rs index 17e244d0649e..d452844cbffb 100644 --- a/crates/project-model/src/rustc_cfg.rs +++ b/crates/project-model/src/rustc_cfg.rs @@ -29,7 +29,7 @@ pub(crate) fn get(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Ve ); res.extend(rustc_cfgs.lines().filter_map(|it| it.parse().ok())); } - Err(e) => tracing::error!("failed to get rustc cfgs: {e:?}"), + Err(e) => tracing::error!("failed to get rustc cfgs: {:?}", e), } res @@ -47,7 +47,7 @@ fn get_rust_cfgs(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Res } match utf8_stdout(cargo_config) { Ok(it) => return Ok(it), - Err(e) => tracing::debug!("{e:?}: falling back to querying rustc for cfgs"), + Err(e) => tracing::debug!("{:?}: falling back to querying rustc for cfgs", e), } } // using unstable cargo features failed, fall back to using plain rustc diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index 133459bf1d21..148fe6f23364 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -33,7 +33,7 @@ threadpool = "1.8.1" rayon = "1.5.1" num_cpus = "1.13.1" mimalloc = { version = "0.1.28", default-features = false, optional = true } -lsp-server = { version = "0.6.0", path = "../../lib/lsp-server" } +lsp-server = "0.5.2" tracing = "0.1.32" tracing-subscriber = { version = "0.3.9", default-features = false, features = [ "env-filter", @@ -75,7 +75,7 @@ jemallocator = { version = "0.4.3", package = "tikv-jemallocator", optional = tr [dev-dependencies] expect-test = "1.2.2" jod-thread = "0.1.2" -xshell = "0.2.1" +xshell = "0.1" test-utils = { path = "../test-utils" } sourcegen = { path = "../sourcegen" } diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 9fd19589999e..b79bab8eb14b 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -631,7 +631,7 @@ impl Config { ) { Some(snippet) => self.snippets.push(snippet), None => errors.push(( - format!("snippet {name} is invalid"), + format!("snippet {} is invalid", name), <serde_json::Error as serde::de::Error>::custom( "snippet path is invalid or triggers are missing", ), diff --git a/crates/rust-analyzer/src/dispatch.rs b/crates/rust-analyzer/src/dispatch.rs index d208ba16cb96..948c31b3e7bf 100644 --- a/crates/rust-analyzer/src/dispatch.rs +++ b/crates/rust-analyzer/src/dispatch.rs @@ -1,7 +1,6 @@ //! See [RequestDispatcher]. use std::{fmt, panic, thread}; -use lsp_server::ExtractError; use serde::{de::DeserializeOwned, Serialize}; use crate::{ @@ -235,10 +234,7 @@ impl<'a> NotificationDispatcher<'a> { }; let params = match not.extract::<N::Params>(N::METHOD) { Ok(it) => it, - Err(ExtractError::JsonError { method, error }) => { - panic!("Invalid request\nMethod: {method}\n error: {error}",) - } - Err(ExtractError::MethodMismatch(not)) => { + Err(not) => { self.not = Some(not); return Ok(self); } diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 4af60035a20e..d08125dfb9f7 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -259,11 +259,7 @@ impl GlobalState { } pub(crate) fn complete_request(&mut self, response: lsp_server::Response) { - let handler = self - .req_queue - .outgoing - .complete(response.id.clone()) - .expect("received response for unknown request"); + let handler = self.req_queue.outgoing.complete(response.id.clone()); handler(self, response) } diff --git a/crates/rust-analyzer/tests/slow-tests/tidy.rs b/crates/rust-analyzer/tests/slow-tests/tidy.rs index 9109617ecff0..fbc4371b9b1f 100644 --- a/crates/rust-analyzer/tests/slow-tests/tidy.rs +++ b/crates/rust-analyzer/tests/slow-tests/tidy.rs @@ -3,15 +3,14 @@ use std::{ path::{Path, PathBuf}, }; -use xshell::{cmd, Shell}; +use xshell::{cmd, pushd, pushenv, read_file}; #[test] fn check_code_formatting() { - let sh = &Shell::new().unwrap(); - sh.change_dir(sourcegen::project_root()); - sh.set_var("RUSTUP_TOOLCHAIN", "stable"); + let _dir = pushd(sourcegen::project_root()).unwrap(); + let _e = pushenv("RUSTUP_TOOLCHAIN", "stable"); - let out = cmd!(sh, "rustfmt --version").read().unwrap(); + let out = cmd!("rustfmt --version").read().unwrap(); if !out.contains("stable") { panic!( "Failed to run rustfmt from toolchain 'stable'. \ @@ -19,27 +18,25 @@ fn check_code_formatting() { ) } - let res = cmd!(sh, "cargo fmt -- --check").run(); + let res = cmd!("cargo fmt -- --check").run(); if res.is_err() { - let _ = cmd!(sh, "cargo fmt").run(); + let _ = cmd!("cargo fmt").run(); } res.unwrap() } #[test] fn check_lsp_extensions_docs() { - let sh = &Shell::new().unwrap(); - let expected_hash = { - let lsp_ext_rs = sh - .read_file(sourcegen::project_root().join("crates/rust-analyzer/src/lsp_ext.rs")) - .unwrap(); + let lsp_ext_rs = + read_file(sourcegen::project_root().join("crates/rust-analyzer/src/lsp_ext.rs")) + .unwrap(); stable_hash(lsp_ext_rs.as_str()) }; let actual_hash = { let lsp_extensions_md = - sh.read_file(sourcegen::project_root().join("docs/dev/lsp-extensions.md")).unwrap(); + read_file(sourcegen::project_root().join("docs/dev/lsp-extensions.md")).unwrap(); let text = lsp_extensions_md .lines() .find_map(|line| line.strip_prefix("lsp_ext.rs hash:")) @@ -65,8 +62,6 @@ Please adjust docs/dev/lsp-extensions.md. #[test] fn files_are_tidy() { - let sh = &Shell::new().unwrap(); - let files = sourcegen::list_files(&sourcegen::project_root().join("crates")); let mut tidy_docs = TidyDocs::default(); @@ -75,7 +70,7 @@ fn files_are_tidy() { let extension = path.extension().unwrap_or_default().to_str().unwrap_or_default(); match extension { "rs" => { - let text = sh.read_file(&path).unwrap(); + let text = read_file(&path).unwrap(); check_todo(&path, &text); check_dbg(&path, &text); check_test_attrs(&path, &text); @@ -85,7 +80,7 @@ fn files_are_tidy() { tidy_marks.visit(&path, &text); } "toml" => { - let text = sh.read_file(&path).unwrap(); + let text = read_file(&path).unwrap(); check_cargo_toml(&path, text); } _ => (), @@ -144,10 +139,8 @@ fn check_cargo_toml(path: &Path, text: String) { #[test] fn check_merge_commits() { - let sh = &Shell::new().unwrap(); - - let bors = cmd!(sh, "git rev-list --merges --author 'bors' HEAD~19..").read().unwrap(); - let all = cmd!(sh, "git rev-list --merges HEAD~19..").read().unwrap(); + let bors = cmd!("git rev-list --merges --author 'bors' HEAD~19..").read().unwrap(); + let all = cmd!("git rev-list --merges HEAD~19..").read().unwrap(); if bors != all { panic!( " @@ -220,8 +213,6 @@ See https://github.com/rust-lang/rust-clippy/issues/5537 for discussion. #[test] fn check_licenses() { - let sh = &Shell::new().unwrap(); - let expected = " 0BSD OR MIT OR Apache-2.0 Apache-2.0 @@ -245,7 +236,7 @@ Zlib OR Apache-2.0 OR MIT .filter(|it| !it.is_empty()) .collect::<Vec<_>>(); - let meta = cmd!(sh, "cargo metadata --format-version 1").read().unwrap(); + let meta = cmd!("cargo metadata --format-version 1").read().unwrap(); let mut licenses = meta .split(|c| c == ',' || c == '{' || c == '}') .filter(|it| it.contains(r#""license""#)) diff --git a/crates/sourcegen/Cargo.toml b/crates/sourcegen/Cargo.toml index 57e183af3f3c..9cfe181c2e0c 100644 --- a/crates/sourcegen/Cargo.toml +++ b/crates/sourcegen/Cargo.toml @@ -10,4 +10,4 @@ rust-version = "1.57" doctest = false [dependencies] -xshell = "0.2.1" +xshell = "0.1" diff --git a/crates/sourcegen/src/lib.rs b/crates/sourcegen/src/lib.rs index 719b35b63032..398e846a14c2 100644 --- a/crates/sourcegen/src/lib.rs +++ b/crates/sourcegen/src/lib.rs @@ -11,7 +11,7 @@ use std::{ path::{Path, PathBuf}, }; -use xshell::{cmd, Shell}; +use xshell::{cmd, pushenv}; pub fn list_rust_files(dir: &Path) -> Vec<PathBuf> { let mut res = list_files(dir); @@ -133,8 +133,8 @@ impl fmt::Display for Location { } } -fn ensure_rustfmt(sh: &Shell) { - let version = cmd!(sh, "rustfmt --version").read().unwrap_or_default(); +fn ensure_rustfmt() { + let version = cmd!("rustfmt --version").read().unwrap_or_default(); if !version.contains("stable") { panic!( "Failed to run rustfmt from toolchain 'stable'. \ @@ -144,11 +144,10 @@ fn ensure_rustfmt(sh: &Shell) { } pub fn reformat(text: String) -> String { - let sh = Shell::new().unwrap(); - sh.set_var("RUSTUP_TOOLCHAIN", "stable"); - ensure_rustfmt(&sh); + let _e = pushenv("RUSTUP_TOOLCHAIN", "stable"); + ensure_rustfmt(); let rustfmt_toml = project_root().join("rustfmt.toml"); - let mut stdout = cmd!(sh, "rustfmt --config-path {rustfmt_toml} --config fn_single_line=true") + let mut stdout = cmd!("rustfmt --config-path {rustfmt_toml} --config fn_single_line=true") .stdin(text) .read() .unwrap(); diff --git a/lib/lsp-server/src/error.rs b/lib/lsp-server/src/error.rs index 4c934d9ecca5..799afb1182a4 100644 --- a/lib/lsp-server/src/error.rs +++ b/lib/lsp-server/src/error.rs @@ -29,7 +29,7 @@ impl fmt::Display for ExtractError<Request> { write!(f, "Method mismatch for request '{}'", req.method) } ExtractError::JsonError { method, error } => { - write!(f, "Invalid request\nMethod: {method}\n error: {error}",) + write!(f, "Invalid request\nMethod: {}\n error: {}", method, error) } } } @@ -43,7 +43,7 @@ impl fmt::Display for ExtractError<Notification> { write!(f, "Method mismatch for notification '{}'", req.method) } ExtractError::JsonError { method, error } => { - write!(f, "Invalid notification\nMethod: {method}\n error: {error}") + write!(f, "Invalid notification\nMethod: {}\n error: {}", method, error) } } } diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 417a58556bd1..0396631bf5b3 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -10,6 +10,6 @@ rust-version = "1.57" anyhow = "1.0.56" flate2 = "1.0.22" write-json = "0.1.2" -xshell = "0.2.1" +xshell = "0.1" xflags = "0.2.4" # Avoid adding more dependencies to this crate diff --git a/xtask/src/dist.rs b/xtask/src/dist.rs index 2ea452377eed..1f1bae8b4baa 100644 --- a/xtask/src/dist.rs +++ b/xtask/src/dist.rs @@ -5,8 +5,9 @@ use std::{ path::{Path, PathBuf}, }; +use anyhow::Result; use flate2::{write::GzEncoder, Compression}; -use xshell::{cmd, Shell}; +use xshell::{cmd, cp, mkdir_p, pushd, pushenv, read_file, rm_rf, write_file}; use crate::{date_iso, flags, project_root}; @@ -15,17 +16,18 @@ const VERSION_NIGHTLY: &str = "0.4"; const VERSION_DEV: &str = "0.5"; // keep this one in sync with `package.json` impl flags::Dist { - pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> { - let stable = sh.var("GITHUB_REF").unwrap_or_default().as_str() == "refs/heads/release"; + pub(crate) fn run(self) -> Result<()> { + let stable = + std::env::var("GITHUB_REF").unwrap_or_default().as_str() == "refs/heads/release"; let project_root = project_root(); let target = Target::get(&project_root); let dist = project_root.join("dist"); - sh.remove_path(&dist)?; - sh.create_dir(&dist)?; + rm_rf(&dist)?; + mkdir_p(&dist)?; let release_channel = if stable { "stable" } else { "nightly" }; - dist_server(sh, release_channel, &target)?; + dist_server(release_channel, &target)?; if let Some(patch_version) = self.client_patch_version { let version = if stable { @@ -34,29 +36,24 @@ impl flags::Dist { // A hack to make VS Code prefer nightly over stable. format!("{}.{}", VERSION_NIGHTLY, patch_version) }; - let release_tag = if stable { date_iso(sh)? } else { "nightly".to_string() }; - dist_client(sh, &version, &release_tag, &target)?; + let release_tag = if stable { date_iso()? } else { "nightly".to_string() }; + dist_client(&version, &release_tag, &target)?; } Ok(()) } } -fn dist_client( - sh: &Shell, - version: &str, - release_tag: &str, - target: &Target, -) -> anyhow::Result<()> { +fn dist_client(version: &str, release_tag: &str, target: &Target) -> Result<()> { let bundle_path = Path::new("editors").join("code").join("server"); - sh.create_dir(&bundle_path)?; - sh.copy_file(&target.server_path, &bundle_path)?; + mkdir_p(&bundle_path)?; + cp(&target.server_path, &bundle_path)?; if let Some(symbols_path) = &target.symbols_path { - sh.copy_file(symbols_path, &bundle_path)?; + cp(symbols_path, &bundle_path)?; } - let _d = sh.push_dir("./editors/code"); + let _d = pushd("./editors/code")?; - let mut patch = Patch::new(sh, "./package.json")?; + let mut patch = Patch::new("./package.json")?; patch .replace( &format!(r#""version": "{}.0-dev""#, VERSION_DEV), @@ -66,26 +63,26 @@ fn dist_client( .replace(r#""$generated-start": {},"#, "") .replace(",\n \"$generated-end\": {}", "") .replace(r#""enabledApiProposals": [],"#, r#""#); - patch.commit(sh)?; + patch.commit()?; Ok(()) } -fn dist_server(sh: &Shell, release_channel: &str, target: &Target) -> anyhow::Result<()> { - let _e = sh.push_env("RUST_ANALYZER_CHANNEL", release_channel); - let _e = sh.push_env("CARGO_PROFILE_RELEASE_LTO", "thin"); +fn dist_server(release_channel: &str, target: &Target) -> Result<()> { + let _e = pushenv("RUST_ANALYZER_CHANNEL", release_channel); + let _e = pushenv("CARGO_PROFILE_RELEASE_LTO", "thin"); // Uncomment to enable debug info for releases. Note that: // * debug info is split on windows and macs, so it does nothing for those platforms, // * on Linux, this blows up the binary size from 8MB to 43MB, which is unreasonable. - // let _e = sh.push_env("CARGO_PROFILE_RELEASE_DEBUG", "1"); + // let _e = pushenv("CARGO_PROFILE_RELEASE_DEBUG", "1"); if target.name.contains("-linux-") { env::set_var("CC", "clang"); } let target_name = &target.name; - cmd!(sh, "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target_name} --release").run()?; + cmd!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target_name} --release").run()?; let dst = Path::new("dist").join(&target.artifact_name); gzip(&target.server_path, &dst.with_extension("gz"))?; @@ -93,7 +90,7 @@ fn dist_server(sh: &Shell, release_channel: &str, target: &Target) -> anyhow::Re Ok(()) } -fn gzip(src_path: &Path, dest_path: &Path) -> anyhow::Result<()> { +fn gzip(src_path: &Path, dest_path: &Path) -> Result<()> { let mut encoder = GzEncoder::new(File::create(dest_path)?, Compression::best()); let mut input = io::BufReader::new(File::open(src_path)?); io::copy(&mut input, &mut encoder)?; @@ -143,9 +140,9 @@ struct Patch { } impl Patch { - fn new(sh: &Shell, path: impl Into<PathBuf>) -> anyhow::Result<Patch> { + fn new(path: impl Into<PathBuf>) -> Result<Patch> { let path = path.into(); - let contents = sh.read_file(&path)?; + let contents = read_file(&path)?; Ok(Patch { path, original_contents: contents.clone(), contents }) } @@ -155,8 +152,8 @@ impl Patch { self } - fn commit(&self, sh: &Shell) -> anyhow::Result<()> { - sh.write_file(&self.path, &self.contents)?; + fn commit(&self) -> Result<()> { + write_file(&self.path, &self.contents)?; Ok(()) } } diff --git a/xtask/src/install.rs b/xtask/src/install.rs index ae978d5512e7..58f386be85a7 100644 --- a/xtask/src/install.rs +++ b/xtask/src/install.rs @@ -3,20 +3,20 @@ use std::{env, path::PathBuf, str}; use anyhow::{bail, format_err, Context, Result}; -use xshell::{cmd, Shell}; +use xshell::{cmd, pushd}; use crate::flags; impl flags::Install { - pub(crate) fn run(self, sh: &Shell) -> Result<()> { + pub(crate) fn run(self) -> Result<()> { if cfg!(target_os = "macos") { - fix_path_for_mac(sh).context("Fix path for mac")?; + fix_path_for_mac().context("Fix path for mac")?; } if let Some(server) = self.server() { - install_server(sh, server).context("install server")?; + install_server(server).context("install server")?; } if let Some(client) = self.client() { - install_client(sh, client).context("install client")?; + install_client(client).context("install client")?; } Ok(()) } @@ -39,14 +39,15 @@ pub(crate) enum Malloc { Jemalloc, } -fn fix_path_for_mac(sh: &Shell) -> Result<()> { +fn fix_path_for_mac() -> Result<()> { let mut vscode_path: Vec<PathBuf> = { const COMMON_APP_PATH: &str = r"/Applications/Visual Studio Code.app/Contents/Resources/app/bin"; const ROOT_DIR: &str = ""; - let home_dir = sh.var("HOME").map_err(|err| { - format_err!("Failed getting HOME from environment with error: {}.", err) - })?; + let home_dir = match env::var("HOME") { + Ok(home) => home, + Err(e) => bail!("Failed getting HOME from environment with error: {}.", e), + }; [ROOT_DIR, &home_dir] .into_iter() @@ -57,33 +58,36 @@ fn fix_path_for_mac(sh: &Shell) -> Result<()> { }; if !vscode_path.is_empty() { - let vars = sh.var_os("PATH").context("Could not get PATH variable from env.")?; + let vars = match env::var_os("PATH") { + Some(path) => path, + None => bail!("Could not get PATH variable from env."), + }; let mut paths = env::split_paths(&vars).collect::<Vec<_>>(); paths.append(&mut vscode_path); let new_paths = env::join_paths(paths).context("build env PATH")?; - sh.set_var("PATH", &new_paths); + env::set_var("PATH", &new_paths); } Ok(()) } -fn install_client(sh: &Shell, client_opt: ClientOpt) -> Result<()> { - let _dir = sh.push_dir("./editors/code"); +fn install_client(client_opt: ClientOpt) -> Result<()> { + let _dir = pushd("./editors/code"); // Package extension. if cfg!(unix) { - cmd!(sh, "npm --version").run().context("`npm` is required to build the VS Code plugin")?; - cmd!(sh, "npm ci").run()?; + cmd!("npm --version").run().context("`npm` is required to build the VS Code plugin")?; + cmd!("npm ci").run()?; - cmd!(sh, "npm run package --scripts-prepend-node-path").run()?; + cmd!("npm run package --scripts-prepend-node-path").run()?; } else { - cmd!(sh, "cmd.exe /c npm --version") + cmd!("cmd.exe /c npm --version") .run() .context("`npm` is required to build the VS Code plugin")?; - cmd!(sh, "cmd.exe /c npm ci").run()?; + cmd!("cmd.exe /c npm ci").run()?; - cmd!(sh, "cmd.exe /c npm run package").run()?; + cmd!("cmd.exe /c npm run package").run()?; }; // Find the appropriate VS Code binary. @@ -100,9 +104,9 @@ fn install_client(sh: &Shell, client_opt: ClientOpt) -> Result<()> { .copied() .find(|&bin| { if cfg!(unix) { - cmd!(sh, "{bin} --version").read().is_ok() + cmd!("{bin} --version").read().is_ok() } else { - cmd!(sh, "cmd.exe /c {bin}.cmd --version").read().is_ok() + cmd!("cmd.exe /c {bin}.cmd --version").read().is_ok() } }) .ok_or_else(|| { @@ -111,11 +115,11 @@ fn install_client(sh: &Shell, client_opt: ClientOpt) -> Result<()> { // Install & verify. let installed_extensions = if cfg!(unix) { - cmd!(sh, "{code} --install-extension rust-analyzer.vsix --force").run()?; - cmd!(sh, "{code} --list-extensions").read()? + cmd!("{code} --install-extension rust-analyzer.vsix --force").run()?; + cmd!("{code} --list-extensions").read()? } else { - cmd!(sh, "cmd.exe /c {code}.cmd --install-extension rust-analyzer.vsix --force").run()?; - cmd!(sh, "cmd.exe /c {code}.cmd --list-extensions").read()? + cmd!("cmd.exe /c {code}.cmd --install-extension rust-analyzer.vsix --force").run()?; + cmd!("cmd.exe /c {code}.cmd --list-extensions").read()? }; if !installed_extensions.contains("rust-analyzer") { @@ -129,14 +133,14 @@ fn install_client(sh: &Shell, client_opt: ClientOpt) -> Result<()> { Ok(()) } -fn install_server(sh: &Shell, opts: ServerOpt) -> Result<()> { +fn install_server(opts: ServerOpt) -> Result<()> { let features = match opts.malloc { Malloc::System => &[][..], Malloc::Mimalloc => &["--features", "mimalloc"], Malloc::Jemalloc => &["--features", "jemalloc"], }; - let cmd = cmd!(sh, "cargo install --path crates/rust-analyzer --locked --force --features force-always-assert {features...}"); + let cmd = cmd!("cargo install --path crates/rust-analyzer --locked --force --features force-always-assert {features...}"); cmd.run()?; Ok(()) } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index df726dc23cba..5e5401ce2885 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -14,16 +14,15 @@ mod release; mod dist; mod metrics; -use anyhow::bail; +use anyhow::{bail, Result}; use std::{ env, path::{Path, PathBuf}, }; -use xshell::{cmd, Shell}; +use xshell::{cmd, cp, pushd, pushenv}; -fn main() -> anyhow::Result<()> { - let sh = &Shell::new()?; - sh.change_dir(project_root()); +fn main() -> Result<()> { + let _d = pushd(project_root())?; let flags = flags::Xtask::from_env()?; match flags.subcommand { @@ -31,21 +30,18 @@ fn main() -> anyhow::Result<()> { println!("{}", flags::Xtask::HELP); Ok(()) } - flags::XtaskCmd::Install(cmd) => cmd.run(sh), - flags::XtaskCmd::FuzzTests(_) => run_fuzzer(sh), - flags::XtaskCmd::Release(cmd) => cmd.run(sh), - flags::XtaskCmd::Promote(cmd) => cmd.run(sh), - flags::XtaskCmd::Dist(cmd) => cmd.run(sh), - flags::XtaskCmd::Metrics(cmd) => cmd.run(sh), + flags::XtaskCmd::Install(cmd) => cmd.run(), + flags::XtaskCmd::FuzzTests(_) => run_fuzzer(), + flags::XtaskCmd::Release(cmd) => cmd.run(), + flags::XtaskCmd::Promote(cmd) => cmd.run(), + flags::XtaskCmd::Dist(cmd) => cmd.run(), + flags::XtaskCmd::Metrics(cmd) => cmd.run(), flags::XtaskCmd::Bb(cmd) => { { - let _d = sh.push_dir("./crates/rust-analyzer"); - cmd!(sh, "cargo build --release --features jemalloc").run()?; + let _d = pushd("./crates/rust-analyzer")?; + cmd!("cargo build --release --features jemalloc").run()?; } - sh.copy_file( - "./target/release/rust-analyzer", - format!("./target/rust-analyzer-{}", cmd.suffix), - )?; + cp("./target/release/rust-analyzer", format!("./target/rust-analyzer-{}", cmd.suffix))?; Ok(()) } } @@ -61,25 +57,25 @@ fn project_root() -> PathBuf { .to_path_buf() } -fn run_fuzzer(sh: &Shell) -> anyhow::Result<()> { - let _d = sh.push_dir("./crates/syntax"); - let _e = sh.push_env("RUSTUP_TOOLCHAIN", "nightly"); - if cmd!(sh, "cargo fuzz --help").read().is_err() { - cmd!(sh, "cargo install cargo-fuzz").run()?; +fn run_fuzzer() -> Result<()> { + let _d = pushd("./crates/syntax")?; + let _e = pushenv("RUSTUP_TOOLCHAIN", "nightly"); + if cmd!("cargo fuzz --help").read().is_err() { + cmd!("cargo install cargo-fuzz").run()?; }; // Expecting nightly rustc - let out = cmd!(sh, "rustc --version").read()?; + let out = cmd!("rustc --version").read()?; if !out.contains("nightly") { bail!("fuzz tests require nightly rustc") } - cmd!(sh, "cargo fuzz run parser").run()?; + cmd!("cargo fuzz run parser").run()?; Ok(()) } -fn date_iso(sh: &Shell) -> anyhow::Result<String> { - let res = cmd!(sh, "date -u +%Y-%m-%d").read()?; +fn date_iso() -> Result<String> { + let res = cmd!("date -u +%Y-%m-%d").read()?; Ok(res) } diff --git a/xtask/src/metrics.rs b/xtask/src/metrics.rs index 3da7419582a8..468b3141cb02 100644 --- a/xtask/src/metrics.rs +++ b/xtask/src/metrics.rs @@ -1,107 +1,99 @@ use std::{ collections::BTreeMap, - env, fs, + env, io::Write as _, path::Path, time::{Instant, SystemTime, UNIX_EPOCH}, }; -use anyhow::{bail, format_err}; -use xshell::{cmd, Shell}; +use anyhow::{bail, format_err, Result}; +use xshell::{cmd, mkdir_p, pushd, pushenv, read_file, rm_rf}; use crate::flags; type Unit = String; impl flags::Metrics { - pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> { - let mut metrics = Metrics::new(sh)?; + pub(crate) fn run(self) -> Result<()> { + let mut metrics = Metrics::new()?; if !self.dry_run { - sh.remove_path("./target/release")?; + rm_rf("./target/release")?; } if !Path::new("./target/rustc-perf").exists() { - sh.create_dir("./target/rustc-perf")?; - cmd!(sh, "git clone https://github.com/rust-lang/rustc-perf.git ./target/rustc-perf") + mkdir_p("./target/rustc-perf")?; + cmd!("git clone https://github.com/rust-lang/rustc-perf.git ./target/rustc-perf") .run()?; } { - let _d = sh.push_dir("./target/rustc-perf"); + let _d = pushd("./target/rustc-perf")?; let revision = &metrics.perf_revision; - cmd!(sh, "git reset --hard {revision}").run()?; + cmd!("git reset --hard {revision}").run()?; } - let _env = sh.push_env("RA_METRICS", "1"); + let _env = pushenv("RA_METRICS", "1"); { // https://github.com/rust-analyzer/rust-analyzer/issues/9997 - let _d = sh.push_dir("target/rustc-perf/collector/benchmarks/webrender"); - cmd!(sh, "cargo update -p url --precise 1.6.1").run()?; + let _d = pushd("target/rustc-perf/collector/benchmarks/webrender")?; + cmd!("cargo update -p url --precise 1.6.1").run()?; } - metrics.measure_build(sh)?; - metrics.measure_analysis_stats_self(sh)?; - metrics.measure_analysis_stats(sh, "ripgrep")?; - metrics.measure_analysis_stats(sh, "webrender")?; - metrics.measure_analysis_stats(sh, "diesel/diesel")?; + metrics.measure_build()?; + metrics.measure_analysis_stats_self()?; + metrics.measure_analysis_stats("ripgrep")?; + metrics.measure_analysis_stats("webrender")?; + metrics.measure_analysis_stats("diesel/diesel")?; if !self.dry_run { - let _d = sh.push_dir("target"); + let _d = pushd("target")?; let metrics_token = env::var("METRICS_TOKEN").unwrap(); cmd!( - sh, "git clone --depth 1 https://{metrics_token}@github.com/rust-analyzer/metrics.git" ) .run()?; { let mut file = - fs::File::options().append(true).open("target/metrics/metrics.json")?; + std::fs::OpenOptions::new().append(true).open("target/metrics/metrics.json")?; writeln!(file, "{}", metrics.json())?; } - let _d = sh.push_dir("metrics"); - cmd!(sh, "git add .").run()?; - cmd!(sh, "git -c user.name=Bot -c user.email=dummy@example.com commit --message 📈") + let _d = pushd("metrics"); + cmd!("git add .").run()?; + cmd!("git -c user.name=Bot -c user.email=dummy@example.com commit --message 📈") .run()?; - cmd!(sh, "git push origin master").run()?; + cmd!("git push origin master").run()?; } - eprintln!("{metrics:#?}"); + eprintln!("{:#?}", metrics); Ok(()) } } impl Metrics { - fn measure_build(&mut self, sh: &Shell) -> anyhow::Result<()> { + fn measure_build(&mut self) -> Result<()> { eprintln!("\nMeasuring build"); - cmd!(sh, "cargo fetch").run()?; + cmd!("cargo fetch").run()?; let time = Instant::now(); - cmd!(sh, "cargo build --release --package rust-analyzer --bin rust-analyzer").run()?; + cmd!("cargo build --release --package rust-analyzer --bin rust-analyzer").run()?; let time = time.elapsed(); self.report("build", time.as_millis() as u64, "ms".into()); Ok(()) } - fn measure_analysis_stats_self(&mut self, sh: &Shell) -> anyhow::Result<()> { - self.measure_analysis_stats_path(sh, "self", ".") + fn measure_analysis_stats_self(&mut self) -> Result<()> { + self.measure_analysis_stats_path("self", ".") } - fn measure_analysis_stats(&mut self, sh: &Shell, bench: &str) -> anyhow::Result<()> { + fn measure_analysis_stats(&mut self, bench: &str) -> Result<()> { self.measure_analysis_stats_path( - sh, bench, &format!("./target/rustc-perf/collector/benchmarks/{}", bench), ) } - fn measure_analysis_stats_path( - &mut self, - sh: &Shell, - name: &str, - path: &str, - ) -> anyhow::Result<()> { - eprintln!("\nMeasuring analysis-stats/{name}"); - let output = - cmd!(sh, "./target/release/rust-analyzer -q analysis-stats --memory-usage {path}") - .read()?; + fn measure_analysis_stats_path(&mut self, name: &str, path: &str) -> Result<()> { + eprintln!("\nMeasuring analysis-stats/{}", name); + let output = cmd!("./target/release/rust-analyzer -q analysis-stats --memory-usage {path}") + .read()?; for (metric, value, unit) in parse_metrics(&output) { - self.report(&format!("analysis-stats/{name}/{metric}"), value, unit.into()); + self.report(&format!("analysis-stats/{}/{}", name, metric), value, unit.into()); } Ok(()) } @@ -137,10 +129,10 @@ struct Host { } impl Metrics { - fn new(sh: &Shell) -> anyhow::Result<Metrics> { - let host = Host::new(sh)?; + fn new() -> Result<Metrics> { + let host = Host::new()?; let timestamp = SystemTime::now(); - let revision = cmd!(sh, "git rev-parse HEAD").read()?; + let revision = cmd!("git rev-parse HEAD").read()?; let perf_revision = "c52ee623e231e7690a93be88d943016968c1036b".into(); Ok(Metrics { host, timestamp, revision, perf_revision, metrics: BTreeMap::new() }) } @@ -169,29 +161,28 @@ impl Metrics { } impl Host { - fn new(sh: &Shell) -> anyhow::Result<Host> { + fn new() -> Result<Host> { if cfg!(not(target_os = "linux")) { bail!("can only collect metrics on Linux "); } - let os = read_field(sh, "/etc/os-release", "PRETTY_NAME=")?.trim_matches('"').to_string(); + let os = read_field("/etc/os-release", "PRETTY_NAME=")?.trim_matches('"').to_string(); - let cpu = read_field(sh, "/proc/cpuinfo", "model name")? - .trim_start_matches(':') - .trim() - .to_string(); + let cpu = + read_field("/proc/cpuinfo", "model name")?.trim_start_matches(':').trim().to_string(); - let mem = read_field(sh, "/proc/meminfo", "MemTotal:")?; + let mem = read_field("/proc/meminfo", "MemTotal:")?; return Ok(Host { os, cpu, mem }); - fn read_field(sh: &Shell, path: &str, field: &str) -> anyhow::Result<String> { - let text = sh.read_file(path)?; + fn read_field(path: &str, field: &str) -> Result<String> { + let text = read_file(path)?; - text.lines() - .find_map(|it| it.strip_prefix(field)) - .map(|it| it.trim().to_string()) - .ok_or_else(|| format_err!("can't parse {}", path)) + let line = text + .lines() + .find(|it| it.starts_with(field)) + .ok_or_else(|| format_err!("can't parse {}", path))?; + Ok(line[field.len()..].trim().to_string()) } } fn to_json(&self, mut obj: write_json::Object<'_>) { diff --git a/xtask/src/release.rs b/xtask/src/release.rs index 04544d6f6b40..2e802339513e 100644 --- a/xtask/src/release.rs +++ b/xtask/src/release.rs @@ -1,15 +1,15 @@ mod changelog; -use xshell::{cmd, Shell}; +use xshell::{cmd, pushd, read_dir, read_file, write_file}; -use crate::{date_iso, flags, is_release_tag, project_root}; +use crate::{date_iso, flags, is_release_tag, project_root, Result}; impl flags::Release { - pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> { + pub(crate) fn run(self) -> Result<()> { if !self.dry_run { - cmd!(sh, "git switch release").run()?; - cmd!(sh, "git fetch upstream --tags --force").run()?; - cmd!(sh, "git reset --hard tags/nightly").run()?; + cmd!("git switch release").run()?; + cmd!("git fetch upstream --tags --force").run()?; + cmd!("git reset --hard tags/nightly").run()?; // The `release` branch sometimes has a couple of cherry-picked // commits for patch releases. If that's the case, just overwrite // it. As we are setting `release` branch to an up-to-date `nightly` @@ -19,24 +19,24 @@ impl flags::Release { // commits -- they'll be kept alive by the tag. More generally, we // don't care about historic releases all that much, it's fine even // to delete old tags. - cmd!(sh, "git push --force").run()?; + cmd!("git push --force").run()?; } // Generates bits of manual.adoc. - cmd!(sh, "cargo test -p ide-assists -p ide-diagnostics -p rust-analyzer -- sourcegen_") + cmd!("cargo test -p ide-assists -p ide-diagnostics -p rust-analyzer -- sourcegen_") .run()?; let website_root = project_root().join("../rust-analyzer.github.io"); { - let _dir = sh.push_dir(&website_root); - cmd!(sh, "git switch src").run()?; - cmd!(sh, "git pull").run()?; + let _dir = pushd(&website_root)?; + cmd!("git switch src").run()?; + cmd!("git pull").run()?; } let changelog_dir = website_root.join("./thisweek/_posts"); - let today = date_iso(sh)?; - let commit = cmd!(sh, "git rev-parse HEAD").read()?; - let changelog_n = sh.read_dir(changelog_dir.as_path())?.len(); + let today = date_iso()?; + let commit = cmd!("git rev-parse HEAD").read()?; + let changelog_n = read_dir(changelog_dir.as_path())?.len(); for adoc in [ "manual.adoc", @@ -48,46 +48,42 @@ impl flags::Release { let src = project_root().join("./docs/user/").join(adoc); let dst = website_root.join(adoc); - let contents = sh.read_file(src)?; - sh.write_file(dst, contents)?; + let contents = read_file(src)?; + write_file(dst, contents)?; } - let tags = cmd!(sh, "git tag --list").read()?; + let tags = cmd!("git tag --list").read()?; let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap(); - let contents = changelog::get_changelog(sh, changelog_n, &commit, prev_tag, &today)?; + let contents = changelog::get_changelog(changelog_n, &commit, prev_tag, &today)?; let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n)); - sh.write_file(&path, &contents)?; + write_file(&path, &contents)?; Ok(()) } } impl flags::Promote { - pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> { - let _dir = sh.push_dir("../rust-rust-analyzer"); - cmd!(sh, "git switch master").run()?; - cmd!(sh, "git fetch upstream").run()?; - cmd!(sh, "git reset --hard upstream/master").run()?; - cmd!(sh, "git submodule update --recursive").run()?; + pub(crate) fn run(self) -> Result<()> { + let _dir = pushd("../rust-rust-analyzer")?; + cmd!("git switch master").run()?; + cmd!("git fetch upstream").run()?; + cmd!("git reset --hard upstream/master").run()?; + cmd!("git submodule update --recursive").run()?; - let date = date_iso(sh)?; - let branch = format!("rust-analyzer-{date}"); - cmd!(sh, "git switch -c {branch}").run()?; + let branch = format!("rust-analyzer-{}", date_iso()?); + cmd!("git switch -c {branch}").run()?; { - let _dir = sh.push_dir("src/tools/rust-analyzer"); - cmd!(sh, "git fetch origin").run()?; - cmd!(sh, "git reset --hard origin/release").run()?; + let _dir = pushd("src/tools/rust-analyzer")?; + cmd!("git fetch origin").run()?; + cmd!("git reset --hard origin/release").run()?; } - cmd!(sh, "git add src/tools/rust-analyzer").run()?; - cmd!(sh, "git commit -m':arrow_up: rust-analyzer'").run()?; + cmd!("git add src/tools/rust-analyzer").run()?; + cmd!("git commit -m':arrow_up: rust-analyzer'").run()?; if !self.dry_run { - cmd!(sh, "git push -u origin {branch}").run()?; - cmd!( - sh, - "xdg-open https://github.com/matklad/rust/pull/new/{branch}?body=r%3F%20%40ghost" - ) - .run()?; + cmd!("git push -u origin {branch}").run()?; + cmd!("xdg-open https://github.com/matklad/rust/pull/new/{branch}?body=r%3F%20%40ghost") + .run()?; } Ok(()) } diff --git a/xtask/src/release/changelog.rs b/xtask/src/release/changelog.rs index 2647f7794f2c..117a2fa90c3a 100644 --- a/xtask/src/release/changelog.rs +++ b/xtask/src/release/changelog.rs @@ -1,11 +1,10 @@ use std::fmt::Write; use std::{env, iter}; -use anyhow::bail; -use xshell::{cmd, Shell}; +use anyhow::{bail}; +use xshell::cmd; pub(crate) fn get_changelog( - sh: &Shell, changelog_n: usize, commit: &str, prev_tag: &str, @@ -16,7 +15,7 @@ pub(crate) fn get_changelog( Err(_) => bail!("Please obtain a personal access token from https://github.com/settings/tokens and set the `GITHUB_TOKEN` environment variable."), }; - let git_log = cmd!(sh, "git log {prev_tag}..HEAD --reverse").read()?; + let git_log = cmd!("git log {prev_tag}..HEAD --reverse").read()?; let mut features = String::new(); let mut fixes = String::new(); let mut internal = String::new(); @@ -31,14 +30,14 @@ pub(crate) fn get_changelog( // we don't use an HTTPS client or JSON parser to keep the build times low let pr = pr_num.to_string(); let pr_json = - cmd!(sh, "curl -s -H {accept} -H {authorization} {pr_url}/{pr}").read()?; - let pr_title = cmd!(sh, "jq .title").stdin(&pr_json).read()?; + cmd!("curl -s -H {accept} -H {authorization} {pr_url}/{pr}").read()?; + let pr_title = cmd!("jq .title").stdin(&pr_json).read()?; let pr_title = unescape(&pr_title[1..pr_title.len() - 1]); - let pr_comment = cmd!(sh, "jq .body").stdin(pr_json).read()?; + let pr_comment = cmd!("jq .body").stdin(pr_json).read()?; let comments_json = - cmd!(sh, "curl -s -H {accept} -H {authorization} {pr_url}/{pr}/comments").read()?; - let pr_comments = cmd!(sh, "jq .[].body").stdin(comments_json).read()?; + cmd!("curl -s -H {accept} -H {authorization} {pr_url}/{pr}/comments").read()?; + let pr_comments = cmd!("jq .[].body").stdin(comments_json).read()?; let l = iter::once(pr_comment.as_str()) .chain(pr_comments.lines())