]> git.proxmox.com Git - rustc.git/blame - vendor/syn/tests/test_round_trip.rs
New upstream version 1.58.1+dfsg1
[rustc.git] / vendor / syn / tests / test_round_trip.rs
CommitLineData
e74abb32
XL
1#![cfg(not(syn_disable_nightly_tests))]
2#![recursion_limit = "1024"]
3#![feature(rustc_private)]
3c0e092e 4#![allow(clippy::if_then_panic)]
e74abb32 5
f035d41b
XL
6extern crate rustc_ast;
7extern crate rustc_errors;
8extern crate rustc_expand;
60c5eb7d 9extern crate rustc_parse as parse;
f035d41b
XL
10extern crate rustc_session;
11extern crate rustc_span;
e74abb32 12
29967ef6 13use crate::common::eq::SpanlessEq;
e74abb32
XL
14use quote::quote;
15use rayon::iter::{IntoParallelIterator, ParallelIterator};
5869c6ff
XL
16use rustc_ast::ast::{
17 AngleBracketedArg, AngleBracketedArgs, Crate, GenericArg, GenericParamKind, Generics,
c295e0f8 18 WhereClause,
5869c6ff
XL
19};
20use rustc_ast::mut_visit::{self, MutVisitor};
f035d41b
XL
21use rustc_errors::PResult;
22use rustc_session::parse::ParseSess;
23use rustc_span::source_map::FilePathMapping;
24use rustc_span::FileName;
5869c6ff 25use std::fs;
e74abb32 26use std::panic;
5869c6ff 27use std::path::Path;
e74abb32
XL
28use std::process;
29use std::sync::atomic::{AtomicUsize, Ordering};
30use std::time::Instant;
29967ef6 31use walkdir::{DirEntry, WalkDir};
e74abb32
XL
32
33#[macro_use]
34mod macros;
35
36#[allow(dead_code)]
37mod common;
38
39mod repo;
40
e74abb32 41#[test]
e74abb32 42fn test_round_trip() {
f035d41b 43 common::rayon_init();
e74abb32
XL
44 repo::clone_rust();
45 let abort_after = common::abort_after();
46 if abort_after == 0 {
47 panic!("Skipping all round_trip tests");
48 }
49
50 let failed = AtomicUsize::new(0);
51
52 WalkDir::new("tests/rust")
53 .sort_by(|a, b| a.file_name().cmp(b.file_name()))
54 .into_iter()
55 .filter_entry(repo::base_dir_filter)
56 .collect::<Result<Vec<DirEntry>, walkdir::Error>>()
57 .unwrap()
58 .into_par_iter()
59 .for_each(|entry| {
60 let path = entry.path();
5869c6ff
XL
61 if !path.is_dir() {
62 test(path, &failed, abort_after);
e74abb32 63 }
5869c6ff 64 });
e74abb32 65
5869c6ff
XL
66 let failed = failed.load(Ordering::SeqCst);
67 if failed > 0 {
68 panic!("{} failures", failed);
69 }
70}
71
72fn test(path: &Path, failed: &AtomicUsize, abort_after: usize) {
73 let content = fs::read_to_string(path).unwrap();
74
75 let start = Instant::now();
76 let (krate, elapsed) = match syn::parse_file(&content) {
77 Ok(krate) => (krate, start.elapsed()),
78 Err(msg) => {
79 errorf!("=== {}: syn failed to parse\n{:?}\n", path.display(), msg);
80 let prev_failed = failed.fetch_add(1, Ordering::SeqCst);
81 if prev_failed + 1 >= abort_after {
82 process::exit(1);
83 }
84 return;
85 }
86 };
87 let back = quote!(#krate).to_string();
88 let edition = repo::edition(path).parse().unwrap();
89
94222f64 90 rustc_span::create_session_if_not_set_then(edition, |_| {
5869c6ff
XL
91 let equal = match panic::catch_unwind(|| {
92 let sess = ParseSess::new(FilePathMapping::empty());
93 let before = match librustc_parse(content, &sess) {
94 Ok(before) => before,
95 Err(mut diagnostic) => {
96 diagnostic.cancel();
97 if diagnostic
98 .message()
99 .starts_with("file not found for module")
100 {
101 errorf!("=== {}: ignore\n", path.display());
e74abb32
XL
102 } else {
103 errorf!(
5869c6ff 104 "=== {}: ignore - librustc failed to parse original content: {}\n",
e74abb32 105 path.display(),
5869c6ff 106 diagnostic.message(),
e74abb32 107 );
e74abb32 108 }
5869c6ff 109 return Err(true);
e74abb32 110 }
5869c6ff
XL
111 };
112 let after = match librustc_parse(back, &sess) {
113 Ok(after) => after,
114 Err(mut diagnostic) => {
115 errorf!("=== {}: librustc failed to parse", path.display());
116 diagnostic.emit();
117 return Err(false);
118 }
119 };
120 Ok((before, after))
121 }) {
122 Err(_) => {
123 errorf!("=== {}: ignoring librustc panic\n", path.display());
124 true
e74abb32 125 }
5869c6ff
XL
126 Ok(Err(equal)) => equal,
127 Ok(Ok((mut before, mut after))) => {
128 normalize(&mut before);
129 normalize(&mut after);
130 if SpanlessEq::eq(&before, &after) {
131 errorf!(
132 "=== {}: pass in {}ms\n",
133 path.display(),
134 elapsed.as_secs() * 1000 + u64::from(elapsed.subsec_nanos()) / 1_000_000
135 );
136 true
137 } else {
138 errorf!(
139 "=== {}: FAIL\nbefore: {:#?}\nafter: {:#?}\n",
140 path.display(),
141 before,
142 after,
143 );
144 false
145 }
146 }
147 };
148 if !equal {
149 let prev_failed = failed.fetch_add(1, Ordering::SeqCst);
150 if prev_failed + 1 >= abort_after {
151 process::exit(1);
152 }
153 }
154 });
e74abb32
XL
155}
156
5869c6ff
XL
157fn librustc_parse(content: String, sess: &ParseSess) -> PResult<Crate> {
158 static COUNTER: AtomicUsize = AtomicUsize::new(0);
159 let counter = COUNTER.fetch_add(1, Ordering::Relaxed);
160 let name = FileName::Custom(format!("test_round_trip{}", counter));
e74abb32
XL
161 parse::parse_crate_from_source_str(name, content, sess)
162}
5869c6ff
XL
163
164fn normalize(krate: &mut Crate) {
165 struct NormalizeVisitor;
166
167 impl MutVisitor for NormalizeVisitor {
168 fn visit_angle_bracketed_parameter_data(&mut self, e: &mut AngleBracketedArgs) {
169 #[derive(Ord, PartialOrd, Eq, PartialEq)]
170 enum Group {
171 Lifetimes,
172 TypesAndConsts,
173 Constraints,
174 }
175 e.args.sort_by_key(|arg| match arg {
176 AngleBracketedArg::Arg(arg) => match arg {
177 GenericArg::Lifetime(_) => Group::Lifetimes,
178 GenericArg::Type(_) | GenericArg::Const(_) => Group::TypesAndConsts,
179 },
180 AngleBracketedArg::Constraint(_) => Group::Constraints,
181 });
182 mut_visit::noop_visit_angle_bracketed_parameter_data(e, self);
183 }
184
185 fn visit_generics(&mut self, e: &mut Generics) {
186 #[derive(Ord, PartialOrd, Eq, PartialEq)]
187 enum Group {
188 Lifetimes,
189 TypesAndConsts,
190 }
191 e.params.sort_by_key(|param| match param.kind {
192 GenericParamKind::Lifetime => Group::Lifetimes,
193 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
194 Group::TypesAndConsts
195 }
196 });
197 mut_visit::noop_visit_generics(e, self);
198 }
c295e0f8
XL
199
200 fn visit_where_clause(&mut self, e: &mut WhereClause) {
201 if e.predicates.is_empty() {
202 e.has_where_token = false;
203 }
204 }
5869c6ff
XL
205 }
206
207 NormalizeVisitor.visit_crate(krate);
208}