• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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