]> git.lizzy.rs Git - rust.git/blob - src/tools/rustfmt/src/skip.rs
Auto merge of #104673 - matthiaskrgr:rollup-85f65ov, r=matthiaskrgr
[rust.git] / src / tools / rustfmt / src / skip.rs
1 //! Module that contains skip related stuffs.
2
3 use rustc_ast::ast;
4 use rustc_ast_pretty::pprust;
5
6 /// Take care of skip name stack. You can update it by attributes slice or
7 /// by other context. Query this context to know if you need skip a block.
8 #[derive(Default, Clone)]
9 pub(crate) struct SkipContext {
10     macros: Vec<String>,
11     attributes: Vec<String>,
12 }
13
14 impl SkipContext {
15     pub(crate) fn update_with_attrs(&mut self, attrs: &[ast::Attribute]) {
16         self.macros.append(&mut get_skip_names("macros", attrs));
17         self.attributes
18             .append(&mut get_skip_names("attributes", attrs));
19     }
20
21     pub(crate) fn update(&mut self, mut other: SkipContext) {
22         self.macros.append(&mut other.macros);
23         self.attributes.append(&mut other.attributes);
24     }
25
26     pub(crate) fn skip_macro(&self, name: &str) -> bool {
27         self.macros.iter().any(|n| n == name)
28     }
29
30     pub(crate) fn skip_attribute(&self, name: &str) -> bool {
31         self.attributes.iter().any(|n| n == name)
32     }
33 }
34
35 static RUSTFMT: &str = "rustfmt";
36 static SKIP: &str = "skip";
37
38 /// Say if you're playing with `rustfmt`'s skip attribute
39 pub(crate) fn is_skip_attr(segments: &[ast::PathSegment]) -> bool {
40     if segments.len() < 2 || segments[0].ident.to_string() != RUSTFMT {
41         return false;
42     }
43     match segments.len() {
44         2 => segments[1].ident.to_string() == SKIP,
45         3 => {
46             segments[1].ident.to_string() == SKIP
47                 && ["macros", "attributes"]
48                     .iter()
49                     .any(|&n| n == pprust::path_segment_to_string(&segments[2]))
50         }
51         _ => false,
52     }
53 }
54
55 fn get_skip_names(kind: &str, attrs: &[ast::Attribute]) -> Vec<String> {
56     let mut skip_names = vec![];
57     let path = format!("{}::{}::{}", RUSTFMT, SKIP, kind);
58     for attr in attrs {
59         // rustc_ast::ast::Path is implemented partialEq
60         // but it is designed for segments.len() == 1
61         if let ast::AttrKind::Normal(normal) = &attr.kind {
62             if pprust::path_to_string(&normal.item.path) != path {
63                 continue;
64             }
65         }
66
67         if let Some(list) = attr.meta_item_list() {
68             for nested_meta_item in list {
69                 if let Some(name) = nested_meta_item.ident() {
70                     skip_names.push(name.to_string());
71                 }
72             }
73         }
74     }
75     skip_names
76 }