rustfmt_nightly/
header.rs1use std::borrow::Cow;
9
10use rustc_ast as ast;
11use rustc_span::Span;
12use rustc_span::symbol::Ident;
13use tracing::debug;
14
15use crate::comment::{combine_strs_with_missing_comments, contains_comment};
16use crate::rewrite::RewriteContext;
17use crate::shape::Shape;
18use crate::utils::rewrite_ident;
19
20pub(crate) fn format_header(
21 context: &RewriteContext<'_>,
22 shape: Shape,
23 parts: Vec<HeaderPart<'_>>,
24) -> String {
25 debug!(?parts, "format_header");
26 let shape = shape.infinite_width();
27
28 let mut parts = parts.into_iter().filter(|x| !x.snippet.is_empty());
30 let Some(part) = parts.next() else {
31 return String::new();
32 };
33
34 let mut result = part.snippet.into_owned();
35 let mut span = part.span;
36
37 for part in parts {
38 debug!(?result, "before combine");
39 let comments_span = span.between(part.span);
40 let comments_snippet = context.snippet(comments_span);
41 result = if contains_comment(comments_snippet) {
42 format!("{result}{comments_snippet}{}", part.snippet)
45 } else {
46 combine_strs_with_missing_comments(
47 context,
48 &result,
49 &part.snippet,
50 comments_span,
51 shape,
52 true,
53 )
54 .unwrap_or_else(|_| format!("{} {}", &result, part.snippet))
55 };
56 debug!(?result);
57 span = part.span;
58 }
59
60 result
61}
62
63#[derive(Debug)]
64pub(crate) struct HeaderPart<'a> {
65 snippet: Cow<'a, str>,
67 span: Span,
68}
69
70impl<'a> HeaderPart<'a> {
71 pub(crate) fn new(snippet: impl Into<Cow<'a, str>>, span: Span) -> Self {
72 Self {
73 snippet: snippet.into(),
74 span,
75 }
76 }
77
78 pub(crate) fn ident(context: &'a RewriteContext<'_>, ident: Ident) -> Self {
79 Self::new(rewrite_ident(context, ident), ident.span)
80 }
81
82 pub(crate) fn visibility(context: &RewriteContext<'_>, vis: &ast::Visibility) -> Self {
83 let snippet = match vis.kind {
84 ast::VisibilityKind::Public => Cow::from("pub"),
85 ast::VisibilityKind::Inherited => Cow::from(""),
86 ast::VisibilityKind::Restricted { ref path, .. } => {
87 let ast::Path { ref segments, .. } = **path;
88 let mut segments_iter =
89 segments.iter().map(|seg| rewrite_ident(context, seg.ident));
90 if path.is_global() {
91 segments_iter
92 .next()
93 .expect("Non-global path in pub(restricted)?");
94 }
95 let is_keyword = |s: &str| s == "crate" || s == "self" || s == "super";
96 let path = segments_iter.collect::<Vec<_>>().join("::");
97 let in_str = if is_keyword(&path) { "" } else { "in " };
98
99 Cow::from(format!("pub({}{})", in_str, path))
101 }
102 };
103
104 Self::new(snippet, vis.span)
105 }
106}