Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/syn/tests/   (Firefox Browser Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 8 kB image not shown  

Quelle  test_round_trip.rs

  Sprache: Rust
 

#![cfg(not(syn_disable_nightly_tests))]
#![cfg(not(miri))]
#![recursion_limit = "1024"]
#![feature(rustc_private)]
#![allow(
    clippy::blocks_in_conditions,
    clippy::manual_assert,
    clippy::manual_let_else,
    clippy::match_like_matches_macro,
    clippy::needless_lifetimes,
    clippy::uninlined_format_args
)]

extern crate rustc_ast;
extern crate rustc_ast_pretty;
extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_error_messages;
extern crate rustc_errors;
extern crate rustc_expand;
extern crate rustc_parse as parse;
extern crate rustc_session;
extern crate rustc_span;

use crate::common::eq::SpanlessEq;
use quote::quote;
use rustc_ast::ast::{
    AngleBracketedArg, AngleBracketedArgs, Crate, GenericArg, GenericParamKind, Generics,
    WhereClause,
};
use rustc_ast::mut_visit::MutVisitor;
use rustc_ast_pretty::pprust;
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_error_messages::{DiagMessage, LazyFallbackBundle};
use rustc_errors::{translation, Diag, PResult};
use rustc_session::parse::ParseSess;
use rustc_span::FileName;
use std::borrow::Cow;
use std::fs;
use std::panic;
use std::path::Path;
use std::process;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Instant;

#[macro_use]
mod macros;

mod common;
mod repo;

#[test]
fn test_round_trip() {
    repo::rayon_init();
    repo::clone_rust();
    let abort_after = repo::abort_after();
    if abort_after == 0 {
        panic!("skipping all round_trip tests");
    }

    let failed = AtomicUsize::new(0);

    repo::for_each_rust_file(|path| test(path, &failed, abort_after));

    let failed = failed.into_inner();
    if failed > 0 {
        panic!("{} failures", failed);
    }
}

fn test(path: &Path, failed: &AtomicUsize, abort_after: usize) {
    let failed = || {
        let prev_failed = failed.fetch_add(1, Ordering::Relaxed);
        if prev_failed + 1 >= abort_after {
            process::exit(1);
        }
    };

    let content = fs::read_to_string(path).unwrap();

    let (back, elapsed) = match panic::catch_unwind(|| {
        let start = Instant::now();
        let result = syn::parse_file(&content);
        let elapsed = start.elapsed();
        result.map(|krate| (quote!(#krate).to_string(), elapsed))
    }) {
        Err(_) => {
            errorf!("=== {}: syn panic\n", path.display());
            failed();
            return;
        }
        Ok(Err(msg)) => {
            errorf!("=== {}: syn failed to parse\n{:?}\n", path.display(), msg);
            failed();
            return;
        }
        Ok(Ok(result)) => result,
    };

    let edition = repo::edition(path).parse().unwrap();

    rustc_span::create_session_if_not_set_then(edition, |_| {
        let equal = match panic::catch_unwind(|| {
            let locale_resources = rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec();
            let sess = ParseSess::new(locale_resources);
            let before = match librustc_parse(content, &sess) {
                Ok(before) => before,
                Err(diagnostic) => {
                    errorf!(
                        "=== {}: ignore - librustc failed to parse original content: {}\n",
                        path.display(),
                        translate_message(&diagnostic),
                    );
                    diagnostic.cancel();
                    return Err(true);
                }
            };
            let after = match librustc_parse(back, &sess) {
                Ok(after) => after,
                Err(diagnostic) => {
                    errorf!("=== {}: librustc failed to parse", path.display());
                    diagnostic.emit();
                    return Err(false);
                }
            };
            Ok((before, after))
        }) {
            Err(_) => {
                errorf!("=== {}: ignoring librustc panic\n", path.display());
                true
            }
            Ok(Err(equal)) => equal,
            Ok(Ok((mut before, mut after))) => {
                normalize(&mut before);
                normalize(&mut after);
                if SpanlessEq::eq(&before, &after) {
                    errorf!(
                        "=== {}: pass in {}ms\n",
                        path.display(),
                        elapsed.as_secs() * 1000 + u64::from(elapsed.subsec_nanos()) / 1_000_000
                    );
                    true
                } else {
                    errorf!(
                        "=== {}: FAIL\n{}\n!=\n{}\n",
                        path.display(),
                        pprust::crate_to_string_for_macros(&before),
                        pprust::crate_to_string_for_macros(&after),
                    );
                    false
                }
            }
        };
        if !equal {
            failed();
        }
    });
}

fn librustc_parse(content: String, sess: &ParseSess) -> PResult<Crate> {
    static COUNTER: AtomicUsize = AtomicUsize::new(0);
    let counter = COUNTER.fetch_add(1, Ordering::Relaxed);
    let name = FileName::Custom(format!("test_round_trip{}", counter));
    let mut parser = parse::new_parser_from_source_str(sess, name, content).unwrap();
    parser.parse_crate_mod()
}

fn translate_message(diagnostic: &Diag) -> Cow<'static, str> {
    thread_local! {
        static FLUENT_BUNDLE: LazyFallbackBundle = {
            let locale_resources = rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec();
            let with_directionality_markers = false;
            rustc_error_messages::fallback_fluent_bundle(locale_resources, with_directionality_markers)
        };
    }

    let message = &diagnostic.messages[0].0;
    let args = translation::to_fluent_args(diagnostic.args.iter());

    let (identifier, attr) = match message {
        DiagMessage::Str(msg) | DiagMessage::Translated(msg) => return msg.clone(),
        DiagMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
    };

    FLUENT_BUNDLE.with(|fluent_bundle| {
        let message = fluent_bundle
            .get_message(identifier)
            .expect("missing diagnostic in fluent bundle");
        let value = match attr {
            Some(attr) => message
                .get_attribute(attr)
                .expect("missing attribute in fluent message")
                .value(),
            None => message.value().expect("missing value in fluent message"),
        };

        let mut err = Vec::new();
        let translated = fluent_bundle.format_pattern(value, Some(&args), &mut err);
        assert!(err.is_empty());
        Cow::Owned(translated.into_owned())
    })
}

fn normalize(krate: &mut Crate) {
    struct NormalizeVisitor;

    impl MutVisitor for NormalizeVisitor {
        fn visit_angle_bracketed_parameter_data(&mut self, e: &le='color:red'>mut AngleBracketedArgs) {
            #[derive(Ord, PartialOrd, Eq, PartialEq)]
            enum Group {
                Lifetimes,
                TypesAndConsts,
                Constraints,
            }
            e.args.sort_by_key(|arg| match arg {
                AngleBracketedArg::Arg(arg) => match arg {
                    GenericArg::Lifetime(_) => Group::Lifetimes,
                    GenericArg::Type(_) | GenericArg::Const(_) => Group::TypesAndConsts,
                },
                AngleBracketedArg::Constraint(_) => Group::Constraints,
            });
            for arg in &mut e.args {
                match arg {
                    AngleBracketedArg::Arg(arg) => self.visit_generic_arg(arg),
                    AngleBracketedArg::Constraint(constraint) => {
                        self.visit_assoc_item_constraint(constraint);
                    }
                }
            }
        }

        fn visit_generics(&mut self, e: &mut Generics) {
            #[derive(Ord, PartialOrd, Eq, PartialEq)]
            enum Group {
                Lifetimes,
                TypesAndConsts,
            }
            e.params.sort_by_key(|param| match param.kind {
                GenericParamKind::Lifetime => Group::Lifetimes,
                GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
                    Group::TypesAndConsts
                }
            });
            e.params
                .flat_map_in_place(|param| self.flat_map_generic_param(param));
            self.visit_where_clause(&mut e.where_clause);
        }

        fn visit_where_clause(&mut self, e: &mut WhereClause) {
            if e.predicates.is_empty() {
                e.has_where_token = false;
            }
        }
    }

    NormalizeVisitor.visit_crate(krate);
}

Messung V0.5 in Prozent
C=100 H=100 G=100

¤ Dauer der Verarbeitung: 0.10 Sekunden  (vorverarbeitet am  2026-06-18) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.