about summary refs log tree commit diff
path: root/tests/ui-fulldeps/rustc_public/check_attribute.rs
blob: 0c34ac4dfe9572e695f2bb3aa233b5318acf1cfb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//@ run-pass
//! Test information regarding type layout.

//@ ignore-stage1
//@ ignore-cross-compile
//@ ignore-remote

#![feature(rustc_private)]

extern crate rustc_hir;
extern crate rustc_middle;

extern crate rustc_driver;
extern crate rustc_interface;
#[macro_use]
extern crate rustc_public;

use rustc_public::{CrateDef, CrateItems};
use std::io::Write;
use std::ops::ControlFlow;

const CRATE_NAME: &str = "input";

/// This function uses the Stable MIR APIs to get information about the test crate.
fn test_stable_mir() -> ControlFlow<()> {
    // Find items in the local crate.
    let items = rustc_public::all_local_items();

    test_tool(&items);

    ControlFlow::Continue(())
}

// Test tool attributes.
fn test_tool(items: &CrateItems) {
    let rustfmt_fn = *get_item(&items, "do_not_format").unwrap();
    let rustfmt_attrs = rustfmt_fn.tool_attrs(&["rustfmt".to_string(), "skip".to_string()]);
    assert_eq!(rustfmt_attrs[0].as_str(), "#[rustfmt::skip]\n");

    let clippy_fn = *get_item(&items, "complex_fn").unwrap();
    let clippy_attrs = clippy_fn.tool_attrs(&["clippy".to_string(),
                                               "cyclomatic_complexity".to_string()]);
    assert_eq!(clippy_attrs[0].as_str(), "#[clippy::cyclomatic_complexity = \"100\"]\n");
}

fn get_item<'a>(
    items: &'a CrateItems,
    name: &str,
) -> Option<&'a rustc_public::CrateItem> {
    items.iter().find(|crate_item| crate_item.name() == name)
}

/// This test will generate and analyze a dummy crate using the stable mir.
/// For that, it will first write the dummy crate into a file.
/// Then it will create a `RustcPublic` using custom arguments and then
/// it will run the compiler.
fn main() {
    let path = "attribute_input.rs";
    generate_input(&path).unwrap();
    let args = &[
        "rustc".to_string(),
        "--crate-type=lib".to_string(),
        "--crate-name".to_string(),
        CRATE_NAME.to_string(),
        path.to_string(),
    ];
    run!(args, test_stable_mir).unwrap();
}

fn generate_input(path: &str) -> std::io::Result<()> {
    let mut file = std::fs::File::create(path)?;
    write!(
        file,
        r#"
        // General metadata applied to the enclosing module or crate.
        #![crate_type = "lib"]

        // Mixed inner and outer attributes.
        #[inline]
        #[deprecated(since = "5.2.0")]
        fn builtins_fn() {{
            #![allow(unused_variables)]

            let x = ();
            let y = ();
            let z = ();
        }}

        // A derive attribute to automatically implement a trait.
        #[derive(Debug, Clone, Copy)]
        struct Foo(u32);

        // A rustfmt tool attribute.
        #[rustfmt::skip]
        fn do_not_format() {{}}

        // A clippy tool attribute.
        #[clippy::cyclomatic_complexity = "100"]
        pub fn complex_fn() {{}}

        // A function with many attributes.
        #[inline]
        #[allow(unused_variables)]
        #[allow(dead_code)]
        #[allow(unused_imports)]
        fn many_attrs() {{
            #![allow(clippy::filter_map)]
            todo!()
        }}
        "#
    )?;
    Ok(())
}