Skip to content

Commit 5df80f2

Browse files
committed
Revert "Merge branch 'struct_macro_trailing_comma' of https://github.com/csmoe/rustfmt into struct_macro_trailing_comma"
This reverts commit 21916b9.
1 parent 848d9fd commit 5df80f2

File tree

604 files changed

+41471
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

604 files changed

+41471
-0
lines changed

CODE_OF_CONDUCT.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# The Rust Code of Conduct
2+
3+
A version of this document [can be found online](https://www.rust-lang.org/conduct.html).
4+
5+
## Conduct
6+
7+
**Contact**: [[email protected]](mailto:[email protected])
8+
9+
* We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic.
10+
* On IRC, please avoid using overtly sexual nicknames or other nicknames that might detract from a friendly, safe and welcoming environment for all.
11+
* Please be kind and courteous. There's no need to be mean or rude.
12+
* Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer.
13+
* Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works.
14+
* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behaviour. We interpret the term "harassment" as including the definition in the <a href="http://citizencodeofconduct.org/">Citizen Code of Conduct</a>; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups.
15+
* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation team][mod_team] immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back.
16+
* Likewise any spamming, trolling, flaming, baiting or other attention-stealing behaviour is not welcome.
17+
18+
## Moderation
19+
20+
21+
These are the policies for upholding our community's standards of conduct. If you feel that a thread needs moderation, please contact the [Rust moderation team][mod_team].
22+
23+
1. Remarks that violate the Rust standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.)
24+
2. Remarks that moderators find inappropriate, whether listed in the code of conduct or not, are also not allowed.
25+
3. Moderators will first respond to such remarks with a warning.
26+
4. If the warning is unheeded, the user will be "kicked," i.e., kicked out of the communication channel to cool off.
27+
5. If the user comes back and continues to make trouble, they will be banned, i.e., indefinitely excluded.
28+
6. Moderators may choose at their discretion to un-ban the user if it was a first offense and they offer the offended party a genuine apology.
29+
7. If a moderator bans someone and you think it was unjustified, please take it up with that moderator, or with a different moderator, **in private**. Complaints about bans in-channel are not allowed.
30+
8. Moderators are held to a higher standard than other community members. If a moderator creates an inappropriate situation, they should expect less leeway than others.
31+
32+
In the Rust community we strive to go the extra step to look out for each other. Don't just aim to be technically unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly if they're off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can drive people away from the community entirely.
33+
34+
And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you could've communicated better — remember that it's your responsibility to make your fellow Rustaceans comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their trust.
35+
36+
The enforcement policies listed above apply to all official Rust venues; including official IRC channels (#rust, #rust-internals, #rust-tools, #rust-libs, #rustc, #rust-beginners, #rust-docs, #rust-community, #rust-lang, and #cargo); GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org (users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion.
37+
38+
*Adapted from the [Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](https://www.contributor-covenant.org/version/1/3/0/).*
39+
40+
[mod_team]: https://www.rust-lang.org/team.html#Moderation-team
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
test!(RunPassPretty {
2+
// comment
3+
path: "src/test/run-pass/pretty",
4+
mode: "pretty",
5+
suite: "run-pass",
6+
default: false,
7+
host: true // comment
8+
});
9+
10+
test!(Test{
11+
field: i32, // comment
12+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
test!(RunPassPretty {
2+
// comment
3+
path: "src/test/run-pass/pretty",
4+
mode: "pretty",
5+
suite: "run-pass",
6+
default: false,
7+
host: true // comment
8+
});
9+
10+
test!(Test {
11+
field: i32 // comment
12+
});

src/attr.rs

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! Format attributes and meta items.
12+
13+
use config::lists::*;
14+
use syntax::ast;
15+
use syntax::codemap::Span;
16+
17+
use comment::{combine_strs_with_missing_comments, contains_comment, rewrite_doc_comment};
18+
use expr::rewrite_literal;
19+
use lists::{itemize_list, write_list, ListFormatting};
20+
use rewrite::{Rewrite, RewriteContext};
21+
use shape::Shape;
22+
use utils::{count_newlines, mk_sp};
23+
24+
use std::cmp;
25+
26+
/// Returns attributes on the given statement.
27+
pub fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] {
28+
match stmt.node {
29+
ast::StmtKind::Local(ref local) => &local.attrs,
30+
ast::StmtKind::Item(ref item) => &item.attrs,
31+
ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => &expr.attrs,
32+
ast::StmtKind::Mac(ref mac) => &mac.2,
33+
}
34+
}
35+
36+
/// Returns attributes that are within `outer_span`.
37+
pub fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> Vec<ast::Attribute> {
38+
attrs
39+
.iter()
40+
.filter(|a| outer_span.lo() <= a.span.lo() && a.span.hi() <= outer_span.hi())
41+
.cloned()
42+
.collect()
43+
}
44+
45+
fn is_derive(attr: &ast::Attribute) -> bool {
46+
attr.check_name("derive")
47+
}
48+
49+
/// Returns the arguments of `#[derive(...)]`.
50+
fn get_derive_args<'a>(context: &'a RewriteContext, attr: &ast::Attribute) -> Option<Vec<&'a str>> {
51+
attr.meta_item_list().map(|meta_item_list| {
52+
meta_item_list
53+
.iter()
54+
.map(|nested_meta_item| context.snippet(nested_meta_item.span))
55+
.collect()
56+
})
57+
}
58+
59+
// Format `#[derive(..)]`, using visual indent & mixed style when we need to go multiline.
60+
fn format_derive(context: &RewriteContext, derive_args: &[&str], shape: Shape) -> Option<String> {
61+
let mut result = String::with_capacity(128);
62+
result.push_str("#[derive(");
63+
// 11 = `#[derive()]`
64+
let initial_budget = shape.width.checked_sub(11)?;
65+
let mut budget = initial_budget;
66+
let num = derive_args.len();
67+
for (i, a) in derive_args.iter().enumerate() {
68+
// 2 = `, ` or `)]`
69+
let width = a.len() + 2;
70+
if width > budget {
71+
if i > 0 {
72+
// Remove trailing whitespace.
73+
result.pop();
74+
}
75+
result.push('\n');
76+
// 9 = `#[derive(`
77+
result.push_str(&(shape.indent + 9).to_string(context.config));
78+
budget = initial_budget;
79+
} else {
80+
budget = budget.checked_sub(width).unwrap_or(0);
81+
}
82+
result.push_str(a);
83+
if i != num - 1 {
84+
result.push_str(", ")
85+
}
86+
}
87+
result.push_str(")]");
88+
Some(result)
89+
}
90+
91+
/// Returns the first group of attributes that fills the given predicate.
92+
/// We consider two doc comments are in different group if they are separated by normal comments.
93+
fn take_while_with_pred<'a, P>(
94+
context: &RewriteContext,
95+
attrs: &'a [ast::Attribute],
96+
pred: P,
97+
) -> &'a [ast::Attribute]
98+
where
99+
P: Fn(&ast::Attribute) -> bool,
100+
{
101+
let mut last_index = 0;
102+
let mut iter = attrs.iter().enumerate().peekable();
103+
while let Some((i, attr)) = iter.next() {
104+
if !pred(attr) {
105+
break;
106+
}
107+
if let Some(&(_, next_attr)) = iter.peek() {
108+
// Extract comments between two attributes.
109+
let span_between_attr = mk_sp(attr.span.hi(), next_attr.span.lo());
110+
let snippet = context.snippet(span_between_attr);
111+
if count_newlines(snippet) >= 2 || snippet.contains('/') {
112+
break;
113+
}
114+
}
115+
last_index = i;
116+
}
117+
if last_index == 0 {
118+
&[]
119+
} else {
120+
&attrs[..last_index + 1]
121+
}
122+
}
123+
124+
/// Rewrite the same kind of attributes at the same time. This includes doc
125+
/// comments and derives.
126+
fn rewrite_first_group_attrs(
127+
context: &RewriteContext,
128+
attrs: &[ast::Attribute],
129+
shape: Shape,
130+
) -> Option<(usize, String)> {
131+
if attrs.is_empty() {
132+
return Some((0, String::new()));
133+
}
134+
// Rewrite doc comments
135+
let sugared_docs = take_while_with_pred(context, attrs, |a| a.is_sugared_doc);
136+
if !sugared_docs.is_empty() {
137+
let snippet = sugared_docs
138+
.iter()
139+
.map(|a| context.snippet(a.span))
140+
.collect::<Vec<_>>()
141+
.join("\n");
142+
return Some((
143+
sugared_docs.len(),
144+
rewrite_doc_comment(&snippet, shape, context.config)?,
145+
));
146+
}
147+
// Rewrite `#[derive(..)]`s.
148+
if context.config.merge_derives() {
149+
let derives = take_while_with_pred(context, attrs, is_derive);
150+
if !derives.is_empty() {
151+
let mut derive_args = vec![];
152+
for derive in derives {
153+
derive_args.append(&mut get_derive_args(context, derive)?);
154+
}
155+
return Some((derives.len(), format_derive(context, &derive_args, shape)?));
156+
}
157+
}
158+
// Rewrite the first attribute.
159+
Some((1, attrs[0].rewrite(context, shape)?))
160+
}
161+
162+
impl Rewrite for ast::NestedMetaItem {
163+
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
164+
match self.node {
165+
ast::NestedMetaItemKind::MetaItem(ref meta_item) => meta_item.rewrite(context, shape),
166+
ast::NestedMetaItemKind::Literal(ref l) => rewrite_literal(context, l, shape),
167+
}
168+
}
169+
}
170+
171+
fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) {
172+
// Look at before and after comment and see if there are any empty lines.
173+
let comment_begin = comment.chars().position(|c| c == '/');
174+
let len = comment_begin.unwrap_or_else(|| comment.len());
175+
let mlb = count_newlines(&comment[..len]) > 1;
176+
let mla = if comment_begin.is_none() {
177+
mlb
178+
} else {
179+
let comment_end = comment.chars().rev().position(|c| !c.is_whitespace());
180+
let len = comment_end.unwrap();
181+
comment
182+
.chars()
183+
.rev()
184+
.take(len)
185+
.filter(|c| *c == '\n')
186+
.count() > 1
187+
};
188+
(if mlb { "\n" } else { "" }, if mla { "\n" } else { "" })
189+
}
190+
191+
impl Rewrite for ast::MetaItem {
192+
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
193+
Some(match self.node {
194+
ast::MetaItemKind::Word => String::from(&*self.name.as_str()),
195+
ast::MetaItemKind::List(ref list) => {
196+
let name = self.name.as_str();
197+
// 1 = `(`, 2 = `]` and `)`
198+
let item_shape = shape
199+
.visual_indent(0)
200+
.shrink_left(name.len() + 1)
201+
.and_then(|s| s.sub_width(2))?;
202+
let items = itemize_list(
203+
context.snippet_provider,
204+
list.iter(),
205+
")",
206+
",",
207+
|nested_meta_item| nested_meta_item.span.lo(),
208+
|nested_meta_item| nested_meta_item.span.hi(),
209+
|nested_meta_item| nested_meta_item.rewrite(context, item_shape),
210+
self.span.lo(),
211+
self.span.hi(),
212+
false,
213+
);
214+
let item_vec = items.collect::<Vec<_>>();
215+
let fmt = ListFormatting {
216+
tactic: DefinitiveListTactic::Mixed,
217+
separator: ",",
218+
trailing_separator: SeparatorTactic::Never,
219+
separator_place: SeparatorPlace::Back,
220+
shape: item_shape,
221+
ends_with_newline: false,
222+
preserve_newline: false,
223+
config: context.config,
224+
};
225+
format!("{}({})", name, write_list(&item_vec, &fmt)?)
226+
}
227+
ast::MetaItemKind::NameValue(ref literal) => {
228+
let name = self.name.as_str();
229+
// 3 = ` = `
230+
let lit_shape = shape.shrink_left(name.len() + 3)?;
231+
// `rewrite_literal` returns `None` when `literal` exceeds max
232+
// width. Since a literal is basically unformattable unless it
233+
// is a string literal (and only if `format_strings` is set),
234+
// we might be better off ignoring the fact that the attribute
235+
// is longer than the max width and contiue on formatting.
236+
// See #2479 for example.
237+
let value = rewrite_literal(context, literal, lit_shape)
238+
.unwrap_or_else(|| context.snippet(literal.span).to_owned());
239+
format!("{} = {}", name, value)
240+
}
241+
})
242+
}
243+
}
244+
245+
impl Rewrite for ast::Attribute {
246+
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
247+
let prefix = match self.style {
248+
ast::AttrStyle::Inner => "#!",
249+
ast::AttrStyle::Outer => "#",
250+
};
251+
let snippet = context.snippet(self.span);
252+
if self.is_sugared_doc {
253+
let doc_shape = Shape {
254+
width: cmp::min(shape.width, context.config.comment_width())
255+
.checked_sub(shape.indent.width())
256+
.unwrap_or(0),
257+
..shape
258+
};
259+
rewrite_doc_comment(snippet, doc_shape, context.config)
260+
} else {
261+
if contains_comment(snippet) {
262+
return Some(snippet.to_owned());
263+
}
264+
// 1 = `[`
265+
let shape = shape.offset_left(prefix.len() + 1)?;
266+
Some(
267+
self.meta()
268+
.and_then(|meta| meta.rewrite(context, shape))
269+
.map_or_else(|| snippet.to_owned(), |rw| format!("{}[{}]", prefix, rw)),
270+
)
271+
}
272+
}
273+
}
274+
275+
impl<'a> Rewrite for [ast::Attribute] {
276+
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
277+
if self.is_empty() {
278+
return Some(String::new());
279+
}
280+
let (first_group_len, first_group_str) = rewrite_first_group_attrs(context, self, shape)?;
281+
if self.len() == 1 || first_group_len == self.len() {
282+
Some(first_group_str)
283+
} else {
284+
let rest_str = self[first_group_len..].rewrite(context, shape)?;
285+
let missing_span = mk_sp(
286+
self[first_group_len - 1].span.hi(),
287+
self[first_group_len].span.lo(),
288+
);
289+
// Preserve an empty line before/after doc comments.
290+
if self[0].is_sugared_doc || self[first_group_len].is_sugared_doc {
291+
let snippet = context.snippet(missing_span);
292+
let (mla, mlb) = has_newlines_before_after_comment(snippet);
293+
let comment = ::comment::recover_missing_comment_in_span(
294+
missing_span,
295+
shape.with_max_width(context.config),
296+
context,
297+
0,
298+
)?;
299+
let comment = if comment.is_empty() {
300+
format!("\n{}", mlb)
301+
} else {
302+
format!("{}{}\n{}", mla, comment, mlb)
303+
};
304+
Some(format!(
305+
"{}{}{}{}",
306+
first_group_str,
307+
comment,
308+
shape.indent.to_string(context.config),
309+
rest_str
310+
))
311+
} else {
312+
combine_strs_with_missing_comments(
313+
context,
314+
&first_group_str,
315+
&rest_str,
316+
missing_span,
317+
shape,
318+
false,
319+
)
320+
}
321+
}
322+
}
323+
}

0 commit comments

Comments
 (0)