• 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