aboutsummaryrefslogtreecommitdiff
path: root/xtask
diff options
context:
space:
mode:
Diffstat (limited to 'xtask')
-rw-r--r--xtask/src/ast_src.rs21
-rw-r--r--xtask/src/codegen/gen_syntax.rs1
-rw-r--r--xtask/src/dist.rs8
-rw-r--r--xtask/src/lib.rs89
-rw-r--r--xtask/src/not_bash.rs60
5 files changed, 97 insertions, 82 deletions
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index 9c02f7c6f..028f7cbe1 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -162,7 +162,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
162 "RECORD_LIT", 162 "RECORD_LIT",
163 "RECORD_FIELD_LIST", 163 "RECORD_FIELD_LIST",
164 "RECORD_FIELD", 164 "RECORD_FIELD",
165 "TRY_BLOCK_EXPR", 165 "EFFECT_EXPR",
166 "BOX_EXPR", 166 "BOX_EXPR",
167 // postfix 167 // postfix
168 "CALL_EXPR", 168 "CALL_EXPR",
@@ -177,7 +177,6 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
177 "PREFIX_EXPR", 177 "PREFIX_EXPR",
178 "RANGE_EXPR", // just weird 178 "RANGE_EXPR", // just weird
179 "BIN_EXPR", 179 "BIN_EXPR",
180 "BLOCK",
181 "EXTERN_BLOCK", 180 "EXTERN_BLOCK",
182 "EXTERN_ITEM_LIST", 181 "EXTERN_ITEM_LIST",
183 "ENUM_VARIANT", 182 "ENUM_VARIANT",
@@ -440,7 +439,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
440 } 439 }
441 struct IfExpr: AttrsOwner { T![if], Condition } 440 struct IfExpr: AttrsOwner { T![if], Condition }
442 struct LoopExpr: AttrsOwner, LoopBodyOwner { T![loop] } 441 struct LoopExpr: AttrsOwner, LoopBodyOwner { T![loop] }
443 struct TryBlockExpr: AttrsOwner { T![try], body: BlockExpr } 442 struct EffectExpr: AttrsOwner { Label, T![try], T![unsafe], T![async], BlockExpr }
444 struct ForExpr: AttrsOwner, LoopBodyOwner { 443 struct ForExpr: AttrsOwner, LoopBodyOwner {
445 T![for], 444 T![for],
446 Pat, 445 Pat,
@@ -451,7 +450,9 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
451 struct ContinueExpr: AttrsOwner { T![continue], T![lifetime] } 450 struct ContinueExpr: AttrsOwner { T![continue], T![lifetime] }
452 struct BreakExpr: AttrsOwner { T![break], T![lifetime], Expr } 451 struct BreakExpr: AttrsOwner { T![break], T![lifetime], Expr }
453 struct Label { T![lifetime] } 452 struct Label { T![lifetime] }
454 struct BlockExpr: AttrsOwner { Label, T![unsafe], Block } 453 struct BlockExpr: AttrsOwner, ModuleItemOwner {
454 T!['{'], statements: [Stmt], Expr, T!['}'],
455 }
455 struct ReturnExpr: AttrsOwner { Expr } 456 struct ReturnExpr: AttrsOwner { Expr }
456 struct CallExpr: ArgListOwner { Expr } 457 struct CallExpr: ArgListOwner { Expr }
457 struct MethodCallExpr: AttrsOwner, ArgListOwner { 458 struct MethodCallExpr: AttrsOwner, ArgListOwner {
@@ -460,7 +461,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
460 struct IndexExpr: AttrsOwner { T!['['], T![']'] } 461 struct IndexExpr: AttrsOwner { T!['['], T![']'] }
461 struct FieldExpr: AttrsOwner { Expr, T![.], NameRef } 462 struct FieldExpr: AttrsOwner { Expr, T![.], NameRef }
462 struct AwaitExpr: AttrsOwner { Expr, T![.], T![await] } 463 struct AwaitExpr: AttrsOwner { Expr, T![.], T![await] }
463 struct TryExpr: AttrsOwner { T![try], Expr } 464 struct TryExpr: AttrsOwner { Expr, T![?] }
464 struct CastExpr: AttrsOwner { Expr, T![as], TypeRef } 465 struct CastExpr: AttrsOwner { Expr, T![as], TypeRef }
465 struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], Expr } 466 struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], Expr }
466 struct PrefixExpr: AttrsOwner { /*PrefixOp,*/ Expr } 467 struct PrefixExpr: AttrsOwner { /*PrefixOp,*/ Expr }
@@ -556,12 +557,6 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
556 T![;], 557 T![;],
557 } 558 }
558 struct Condition { T![let], Pat, T![=], Expr } 559 struct Condition { T![let], Pat, T![=], Expr }
559 struct Block: AttrsOwner, ModuleItemOwner {
560 T!['{'],
561 statements: [Stmt],
562 Expr,
563 T!['}'],
564 }
565 struct ParamList { 560 struct ParamList {
566 T!['('], 561 T!['('],
567 SelfParam, 562 SelfParam,
@@ -595,7 +590,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
595 qualifier: Path, 590 qualifier: Path,
596 } 591 }
597 struct PathSegment { 592 struct PathSegment {
598 T![::], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>] 593 T![::], T![crate], T![self], T![super], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>]
599 } 594 }
600 struct TypeArgList { 595 struct TypeArgList {
601 T![::], 596 T![::],
@@ -722,7 +717,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
722 FieldExpr, 717 FieldExpr,
723 AwaitExpr, 718 AwaitExpr,
724 TryExpr, 719 TryExpr,
725 TryBlockExpr, 720 EffectExpr,
726 CastExpr, 721 CastExpr,
727 RefExpr, 722 RefExpr,
728 PrefixExpr, 723 PrefixExpr,
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs
index e9dc09552..8028575c5 100644
--- a/xtask/src/codegen/gen_syntax.rs
+++ b/xtask/src/codegen/gen_syntax.rs
@@ -432,6 +432,7 @@ impl Field<'_> {
432 ":" => "colon", 432 ":" => "colon",
433 "::" => "coloncolon", 433 "::" => "coloncolon",
434 "#" => "pound", 434 "#" => "pound",
435 "?" => "question_mark",
435 _ => name, 436 _ => name,
436 }; 437 };
437 format_ident!("{}_token", name) 438 format_ident!("{}_token", name)
diff --git a/xtask/src/dist.rs b/xtask/src/dist.rs
index a56eeef8d..aef68089e 100644
--- a/xtask/src/dist.rs
+++ b/xtask/src/dist.rs
@@ -50,21 +50,19 @@ fn dist_server(nightly: bool) -> Result<()> {
50 if cfg!(target_os = "linux") { 50 if cfg!(target_os = "linux") {
51 std::env::set_var("CC", "clang"); 51 std::env::set_var("CC", "clang");
52 run!( 52 run!(
53 "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release 53 "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release"
54 --target x86_64-unknown-linux-musl
55 "
56 // We'd want to add, but that requires setting the right linker somehow 54 // We'd want to add, but that requires setting the right linker somehow
57 // --features=jemalloc 55 // --features=jemalloc
58 )?; 56 )?;
59 if !nightly { 57 if !nightly {
60 run!("strip ./target/x86_64-unknown-linux-musl/release/rust-analyzer")?; 58 run!("strip ./target/release/rust-analyzer")?;
61 } 59 }
62 } else { 60 } else {
63 run!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release")?; 61 run!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release")?;
64 } 62 }
65 63
66 let (src, dst) = if cfg!(target_os = "linux") { 64 let (src, dst) = if cfg!(target_os = "linux") {
67 ("./target/x86_64-unknown-linux-musl/release/rust-analyzer", "./dist/rust-analyzer-linux") 65 ("./target/release/rust-analyzer", "./dist/rust-analyzer-linux")
68 } else if cfg!(target_os = "windows") { 66 } else if cfg!(target_os = "windows") {
69 ("./target/release/rust-analyzer.exe", "./dist/rust-analyzer-windows.exe") 67 ("./target/release/rust-analyzer.exe", "./dist/rust-analyzer-windows.exe")
70 } else if cfg!(target_os = "macos") { 68 } else if cfg!(target_os = "macos") {
diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs
index ec824a518..2b7a461e5 100644
--- a/xtask/src/lib.rs
+++ b/xtask/src/lib.rs
@@ -10,23 +10,19 @@ pub mod pre_commit;
10pub mod codegen; 10pub mod codegen;
11mod ast_src; 11mod ast_src;
12 12
13use anyhow::Context;
14use std::{ 13use std::{
15 env, 14 env,
16 io::Write,
17 path::{Path, PathBuf}, 15 path::{Path, PathBuf},
18 process::{Command, Stdio},
19}; 16};
17
20use walkdir::{DirEntry, WalkDir}; 18use walkdir::{DirEntry, WalkDir};
21 19
22use crate::{ 20use crate::{
23 codegen::Mode, 21 codegen::Mode,
24 not_bash::{date_iso, fs2, pushd, rm_rf, run}, 22 not_bash::{date_iso, fs2, pushd, pushenv, rm_rf, run},
25}; 23};
26 24
27pub use anyhow::Result; 25pub use anyhow::{bail, Context as _, Result};
28
29const TOOLCHAIN: &str = "stable";
30 26
31pub fn project_root() -> PathBuf { 27pub fn project_root() -> PathBuf {
32 Path::new( 28 Path::new(
@@ -55,54 +51,44 @@ pub fn rust_files(path: &Path) -> impl Iterator<Item = PathBuf> {
55 51
56pub fn run_rustfmt(mode: Mode) -> Result<()> { 52pub fn run_rustfmt(mode: Mode) -> Result<()> {
57 let _dir = pushd(project_root()); 53 let _dir = pushd(project_root());
54 let _e = pushenv("RUSTUP_TOOLCHAIN", "stable");
58 ensure_rustfmt()?; 55 ensure_rustfmt()?;
59 56 match mode {
60 let check = if mode == Mode::Verify { "--check" } else { "" }; 57 Mode::Overwrite => run!("cargo fmt"),
61 run!("rustup run {} -- cargo fmt -- {}", TOOLCHAIN, check)?; 58 Mode::Verify => run!("cargo fmt -- --check"),
59 }?;
62 Ok(()) 60 Ok(())
63} 61}
64 62
65fn reformat(text: impl std::fmt::Display) -> Result<String> { 63fn reformat(text: impl std::fmt::Display) -> Result<String> {
64 let _e = pushenv("RUSTUP_TOOLCHAIN", "stable");
66 ensure_rustfmt()?; 65 ensure_rustfmt()?;
67 let mut rustfmt = Command::new("rustup") 66 let stdout = run!(
68 .args(&["run", TOOLCHAIN, "--", "rustfmt", "--config-path"]) 67 "rustfmt --config-path {} --config fn_single_line=true", project_root().join("rustfmt.toml").display();
69 .arg(project_root().join("rustfmt.toml")) 68 <text.to_string().as_bytes()
70 .args(&["--config", "fn_single_line=true"]) 69 )?;
71 .stdin(Stdio::piped())
72 .stdout(Stdio::piped())
73 .spawn()?;
74 write!(rustfmt.stdin.take().unwrap(), "{}", text)?;
75 let output = rustfmt.wait_with_output()?;
76 let stdout = String::from_utf8(output.stdout)?;
77 let preamble = "Generated file, do not edit by hand, see `xtask/src/codegen`"; 70 let preamble = "Generated file, do not edit by hand, see `xtask/src/codegen`";
78 Ok(format!("//! {}\n\n{}", preamble, stdout)) 71 Ok(format!("//! {}\n\n{}\n", preamble, stdout))
79} 72}
80 73
81fn ensure_rustfmt() -> Result<()> { 74fn ensure_rustfmt() -> Result<()> {
82 match Command::new("rustup") 75 let out = run!("rustfmt --version")?;
83 .args(&["run", TOOLCHAIN, "--", "cargo", "fmt", "--version"]) 76 if !out.contains("stable") {
84 .stderr(Stdio::null()) 77 bail!(
85 .stdout(Stdio::null()) 78 "Failed to run rustfmt from toolchain 'stable'. \
86 .status() 79 Please run `rustup component add rustfmt --toolchain stable` to install it.",
87 { 80 )
88 Ok(status) if status.success() => return Ok(()), 81 }
89 _ => (),
90 };
91 run!("rustup toolchain install {}", TOOLCHAIN)?;
92 run!("rustup component add rustfmt --toolchain {}", TOOLCHAIN)?;
93 Ok(()) 82 Ok(())
94} 83}
95 84
96pub fn run_clippy() -> Result<()> { 85pub fn run_clippy() -> Result<()> {
97 match Command::new("rustup") 86 if run!("cargo clippy --version").is_err() {
98 .args(&["run", TOOLCHAIN, "--", "cargo", "clippy", "--version"]) 87 bail!(
99 .stderr(Stdio::null()) 88 "Failed run cargo clippy. \
100 .stdout(Stdio::null()) 89 Please run `rustup component add clippy` to install it.",
101 .status() 90 )
102 { 91 }
103 Ok(status) if status.success() => (),
104 _ => install_clippy().context("install clippy")?,
105 };
106 92
107 let allowed_lints = [ 93 let allowed_lints = [
108 "clippy::collapsible_if", 94 "clippy::collapsible_if",
@@ -110,27 +96,24 @@ pub fn run_clippy() -> Result<()> {
110 "clippy::nonminimal_bool", 96 "clippy::nonminimal_bool",
111 "clippy::redundant_pattern_matching", 97 "clippy::redundant_pattern_matching",
112 ]; 98 ];
113 run!( 99 run!("cargo clippy --all-features --all-targets -- -A {}", allowed_lints.join(" -A "))?;
114 "rustup run {} -- cargo clippy --all-features --all-targets -- -A {}",
115 TOOLCHAIN,
116 allowed_lints.join(" -A ")
117 )?;
118 Ok(())
119}
120
121fn install_clippy() -> Result<()> {
122 run!("rustup toolchain install {}", TOOLCHAIN)?;
123 run!("rustup component add clippy --toolchain {}", TOOLCHAIN)?;
124 Ok(()) 100 Ok(())
125} 101}
126 102
127pub fn run_fuzzer() -> Result<()> { 103pub fn run_fuzzer() -> Result<()> {
128 let _d = pushd("./crates/ra_syntax"); 104 let _d = pushd("./crates/ra_syntax");
105 let _e = pushenv("RUSTUP_TOOLCHAIN", "nightly");
129 if run!("cargo fuzz --help").is_err() { 106 if run!("cargo fuzz --help").is_err() {
130 run!("cargo install cargo-fuzz")?; 107 run!("cargo install cargo-fuzz")?;
131 }; 108 };
132 109
133 run!("rustup run nightly -- cargo fuzz run parser")?; 110 // Expecting nightly rustc
111 let out = run!("rustc --version")?;
112 if !out.contains("nightly") {
113 bail!("fuzz tests require nightly rustc")
114 }
115
116 run!("cargo fuzz run parser")?;
134 Ok(()) 117 Ok(())
135} 118}
136 119
diff --git a/xtask/src/not_bash.rs b/xtask/src/not_bash.rs
index ef1699934..a6431e586 100644
--- a/xtask/src/not_bash.rs
+++ b/xtask/src/not_bash.rs
@@ -3,6 +3,8 @@
3use std::{ 3use std::{
4 cell::RefCell, 4 cell::RefCell,
5 env, 5 env,
6 ffi::OsString,
7 io::Write,
6 path::{Path, PathBuf}, 8 path::{Path, PathBuf},
7 process::{Command, Stdio}, 9 process::{Command, Stdio},
8}; 10};
@@ -57,7 +59,10 @@ macro_rules! _run {
57 run!($($expr),*; echo = true) 59 run!($($expr),*; echo = true)
58 }; 60 };
59 ($($expr:expr),* ; echo = $echo:expr) => { 61 ($($expr:expr),* ; echo = $echo:expr) => {
60 $crate::not_bash::run_process(format!($($expr),*), $echo) 62 $crate::not_bash::run_process(format!($($expr),*), $echo, None)
63 };
64 ($($expr:expr),* ; <$stdin:expr) => {
65 $crate::not_bash::run_process(format!($($expr),*), false, Some($stdin))
61 }; 66 };
62} 67}
63pub(crate) use _run as run; 68pub(crate) use _run as run;
@@ -77,6 +82,21 @@ impl Drop for Pushd {
77 } 82 }
78} 83}
79 84
85pub struct Pushenv {
86 _p: (),
87}
88
89pub fn pushenv(var: &str, value: &str) -> Pushenv {
90 Env::with(|env| env.pushenv(var.into(), value.into()));
91 Pushenv { _p: () }
92}
93
94impl Drop for Pushenv {
95 fn drop(&mut self) {
96 Env::with(|env| env.popenv())
97 }
98}
99
80pub fn rm_rf(path: impl AsRef<Path>) -> Result<()> { 100pub fn rm_rf(path: impl AsRef<Path>) -> Result<()> {
81 let path = path.as_ref(); 101 let path = path.as_ref();
82 if !path.exists() { 102 if !path.exists() {
@@ -90,15 +110,15 @@ pub fn rm_rf(path: impl AsRef<Path>) -> Result<()> {
90} 110}
91 111
92#[doc(hidden)] 112#[doc(hidden)]
93pub fn run_process(cmd: String, echo: bool) -> Result<String> { 113pub fn run_process(cmd: String, echo: bool, stdin: Option<&[u8]>) -> Result<String> {
94 run_process_inner(&cmd, echo).with_context(|| format!("process `{}` failed", cmd)) 114 run_process_inner(&cmd, echo, stdin).with_context(|| format!("process `{}` failed", cmd))
95} 115}
96 116
97pub fn date_iso() -> Result<String> { 117pub fn date_iso() -> Result<String> {
98 run!("date --iso --utc") 118 run!("date --iso --utc")
99} 119}
100 120
101fn run_process_inner(cmd: &str, echo: bool) -> Result<String> { 121fn run_process_inner(cmd: &str, echo: bool, stdin: Option<&[u8]>) -> Result<String> {
102 let mut args = shelx(cmd); 122 let mut args = shelx(cmd);
103 let binary = args.remove(0); 123 let binary = args.remove(0);
104 let current_dir = Env::with(|it| it.cwd().to_path_buf()); 124 let current_dir = Env::with(|it| it.cwd().to_path_buf());
@@ -107,12 +127,17 @@ fn run_process_inner(cmd: &str, echo: bool) -> Result<String> {
107 println!("> {}", cmd) 127 println!("> {}", cmd)
108 } 128 }
109 129
110 let output = Command::new(binary) 130 let mut command = Command::new(binary);
111 .args(args) 131 command.args(args).current_dir(current_dir).stderr(Stdio::inherit());
112 .current_dir(current_dir) 132 let output = match stdin {
113 .stdin(Stdio::null()) 133 None => command.stdin(Stdio::null()).output(),
114 .stderr(Stdio::inherit()) 134 Some(stdin) => {
115 .output()?; 135 command.stdin(Stdio::piped()).stdout(Stdio::piped());
136 let mut process = command.spawn()?;
137 process.stdin.take().unwrap().write_all(stdin)?;
138 process.wait_with_output()
139 }
140 }?;
116 let stdout = String::from_utf8(output.stdout)?; 141 let stdout = String::from_utf8(output.stdout)?;
117 142
118 if echo { 143 if echo {
@@ -133,13 +158,15 @@ fn shelx(cmd: &str) -> Vec<String> {
133 158
134struct Env { 159struct Env {
135 pushd_stack: Vec<PathBuf>, 160 pushd_stack: Vec<PathBuf>,
161 pushenv_stack: Vec<(OsString, Option<OsString>)>,
136} 162}
137 163
138impl Env { 164impl Env {
139 fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T { 165 fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T {
140 thread_local! { 166 thread_local! {
141 static ENV: RefCell<Env> = RefCell::new(Env { 167 static ENV: RefCell<Env> = RefCell::new(Env {
142 pushd_stack: vec![env::current_dir().unwrap()] 168 pushd_stack: vec![env::current_dir().unwrap()],
169 pushenv_stack: vec![],
143 }); 170 });
144 } 171 }
145 ENV.with(|it| f(&mut *it.borrow_mut())) 172 ENV.with(|it| f(&mut *it.borrow_mut()))
@@ -154,6 +181,17 @@ impl Env {
154 self.pushd_stack.pop().unwrap(); 181 self.pushd_stack.pop().unwrap();
155 env::set_current_dir(self.cwd()).unwrap(); 182 env::set_current_dir(self.cwd()).unwrap();
156 } 183 }
184 fn pushenv(&mut self, var: OsString, value: OsString) {
185 self.pushenv_stack.push((var.clone(), env::var_os(&var)));
186 env::set_var(var, value)
187 }
188 fn popenv(&mut self) {
189 let (var, value) = self.pushenv_stack.pop().unwrap();
190 match value {
191 None => env::remove_var(var),
192 Some(value) => env::set_var(var, value),
193 }
194 }
157 fn cwd(&self) -> &Path { 195 fn cwd(&self) -> &Path {
158 self.pushd_stack.last().unwrap() 196 self.pushd_stack.last().unwrap()
159 } 197 }