1 #![allow(clippy::manual_assert)] 2 3 mod progress; 4 5 use self::progress::Progress; 6 use anyhow::Result; 7 use flate2::read::GzDecoder; 8 use std::fs; 9 use std::path::Path; 10 use tar::Archive; 11 use walkdir::DirEntry; 12 13 const REVISION: &str = "98ad6a5519651af36e246c0335c964dd52c554ba"; 14 15 #[rustfmt::skip] 16 static EXCLUDE_FILES: &[&str] = &[ 17 // TODO: impl ~const T {} 18 // https://github.com/dtolnay/syn/issues/1051 19 "src/test/ui/rfc-2632-const-trait-impl/syntax.rs", 20 21 // Compile-fail expr parameter in const generic position: f::<1 + 2>() 22 "src/test/ui/const-generics/early/closing-args-token.rs", 23 "src/test/ui/const-generics/early/const-expression-parameter.rs", 24 25 // Need at least one trait in impl Trait, no such type as impl 'static 26 "src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs", 27 28 // Deprecated anonymous parameter syntax in traits 29 "src/test/ui/issues/issue-13105.rs", 30 "src/test/ui/issues/issue-13775.rs", 31 "src/test/ui/issues/issue-34074.rs", 32 "src/test/ui/proc-macro/trait-fn-args-2015.rs", 33 "src/tools/rustfmt/tests/source/trait.rs", 34 "src/tools/rustfmt/tests/target/trait.rs", 35 36 // Various extensions to Rust syntax made up by rust-analyzer 37 "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0012_type_item_where_clause.rs", 38 "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rs", 39 "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0131_existential_type.rs", 40 "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0179_use_tree_abs_star.rs", 41 "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rs", 42 "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0015_use_tree.rs", 43 "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0029_range_forms.rs", 44 "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rs", 45 "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0055_dot_dot_dot.rs", 46 "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0068_item_modifiers.rs", 47 "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0031_block_inner_attrs.rs", 48 "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0045_ambiguous_trait_object.rs", 49 "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0046_mutable_const_item.rs", 50 51 // Placeholder syntax for "throw expressions" 52 "src/test/pretty/yeet-expr.rs", 53 "src/test/ui/try-trait/yeet-for-option.rs", 54 "src/test/ui/try-trait/yeet-for-result.rs", 55 56 // Excessive nesting 57 "src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs", 58 59 // Testing tools on invalid syntax 60 "src/test/run-make/translation/test.rs", 61 "src/test/ui/generics/issue-94432-garbage-ice.rs", 62 "src/tools/rustfmt/tests/coverage/target/comments.rs", 63 "src/tools/rustfmt/tests/parser/issue-4126/invalid.rs", 64 "src/tools/rustfmt/tests/parser/issue_4418.rs", 65 "src/tools/rustfmt/tests/parser/unclosed-delims/issue_4466.rs", 66 "src/tools/rustfmt/tests/source/configs/disable_all_formatting/true.rs", 67 "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/false.rs", 68 "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/true.rs", 69 "src/tools/rustfmt/tests/source/type.rs", 70 "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/false.rs", 71 "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/true.rs", 72 "src/tools/rustfmt/tests/target/type.rs", 73 74 // Generated file containing a top-level expression, used with `include!` 75 "compiler/rustc_codegen_gcc/src/intrinsic/archs.rs", 76 77 // Clippy lint lists represented as expressions 78 "src/tools/clippy/clippy_lints/src/lib.deprecated.rs", 79 "src/tools/clippy/clippy_lints/src/lib.register_all.rs", 80 "src/tools/clippy/clippy_lints/src/lib.register_cargo.rs", 81 "src/tools/clippy/clippy_lints/src/lib.register_complexity.rs", 82 "src/tools/clippy/clippy_lints/src/lib.register_correctness.rs", 83 "src/tools/clippy/clippy_lints/src/lib.register_internal.rs", 84 "src/tools/clippy/clippy_lints/src/lib.register_lints.rs", 85 "src/tools/clippy/clippy_lints/src/lib.register_nursery.rs", 86 "src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs", 87 "src/tools/clippy/clippy_lints/src/lib.register_perf.rs", 88 "src/tools/clippy/clippy_lints/src/lib.register_restriction.rs", 89 "src/tools/clippy/clippy_lints/src/lib.register_style.rs", 90 "src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs", 91 92 // Not actually test cases 93 "src/test/ui/lint/expansion-time-include.rs", 94 "src/test/ui/macros/auxiliary/macro-comma-support.rs", 95 "src/test/ui/macros/auxiliary/macro-include-items-expr.rs", 96 "src/test/ui/macros/include-single-expr-helper.rs", 97 "src/test/ui/macros/include-single-expr-helper-1.rs", 98 "src/test/ui/parser/issues/auxiliary/issue-21146-inc.rs", 99 ]; 100 101 #[rustfmt::skip] 102 static EXCLUDE_DIRS: &[&str] = &[ 103 // Inputs that intentionally do not parse 104 "src/tools/rust-analyzer/crates/parser/test_data/parser/err", 105 "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err", 106 107 // Inputs that lex but do not necessarily parse 108 "src/tools/rust-analyzer/crates/parser/test_data/lexer", 109 110 // Inputs that used to crash rust-analyzer, but aren't necessarily supposed to parse 111 "src/tools/rust-analyzer/crates/syntax/test_data/parser/fuzz-failures", 112 "src/tools/rust-analyzer/crates/syntax/test_data/reparse/fuzz-failures", 113 ]; 114 base_dir_filter(entry: &DirEntry) -> bool115 pub fn base_dir_filter(entry: &DirEntry) -> bool { 116 let path = entry.path(); 117 118 let mut path_string = path.to_string_lossy(); 119 if cfg!(windows) { 120 path_string = path_string.replace('\\', "/").into(); 121 } 122 let path_string = if path_string == "tests/rust" { 123 return true; 124 } else if let Some(path) = path_string.strip_prefix("tests/rust/") { 125 path 126 } else { 127 panic!("unexpected path in Rust dist: {}", path_string); 128 }; 129 130 if path.is_dir() { 131 return !EXCLUDE_DIRS.contains(&path_string); 132 } 133 134 if path.extension().map_or(true, |e| e != "rs") { 135 return false; 136 } 137 138 if path_string.starts_with("src/test/ui") || path_string.starts_with("src/test/rustdoc-ui") { 139 let stderr_path = path.with_extension("stderr"); 140 if stderr_path.exists() { 141 // Expected to fail in some way 142 return false; 143 } 144 } 145 146 !EXCLUDE_FILES.contains(&path_string) 147 } 148 149 #[allow(dead_code)] edition(path: &Path) -> &'static str150 pub fn edition(path: &Path) -> &'static str { 151 if path.ends_with("dyn-2015-no-warnings-without-lints.rs") { 152 "2015" 153 } else { 154 "2018" 155 } 156 } 157 clone_rust()158 pub fn clone_rust() { 159 let needs_clone = match fs::read_to_string("tests/rust/COMMIT") { 160 Err(_) => true, 161 Ok(contents) => contents.trim() != REVISION, 162 }; 163 if needs_clone { 164 download_and_unpack().unwrap(); 165 } 166 let mut missing = String::new(); 167 let test_src = Path::new("tests/rust"); 168 for exclude in EXCLUDE_FILES { 169 if !test_src.join(exclude).is_file() { 170 missing += "\ntests/rust/"; 171 missing += exclude; 172 } 173 } 174 for exclude in EXCLUDE_DIRS { 175 if !test_src.join(exclude).is_dir() { 176 missing += "\ntests/rust/"; 177 missing += exclude; 178 missing += "/"; 179 } 180 } 181 if !missing.is_empty() { 182 panic!("excluded test file does not exist:{}\n", missing); 183 } 184 } 185 download_and_unpack() -> Result<()>186 fn download_and_unpack() -> Result<()> { 187 let url = format!( 188 "https://github.com/rust-lang/rust/archive/{}.tar.gz", 189 REVISION 190 ); 191 let response = reqwest::blocking::get(url)?.error_for_status()?; 192 let progress = Progress::new(response); 193 let decoder = GzDecoder::new(progress); 194 let mut archive = Archive::new(decoder); 195 let prefix = format!("rust-{}", REVISION); 196 197 let tests_rust = Path::new("tests/rust"); 198 if tests_rust.exists() { 199 fs::remove_dir_all(tests_rust)?; 200 } 201 202 for entry in archive.entries()? { 203 let mut entry = entry?; 204 let path = entry.path()?; 205 if path == Path::new("pax_global_header") { 206 continue; 207 } 208 let relative = path.strip_prefix(&prefix)?; 209 let out = tests_rust.join(relative); 210 entry.unpack(&out)?; 211 } 212 213 fs::write("tests/rust/COMMIT", REVISION)?; 214 Ok(()) 215 } 216