///
/// **Examples:**
/// ```rust
-/// /// Do something with the foo_bar parameter. See also that::other::module::foo.
+/// /// Do something with the foo_bar parameter. See also
+/// that::other::module::foo.
/// // ^ `foo_bar` and `that::other::module::foo` should be ticked.
/// fn doit(foo_bar) { .. }
/// ```
impl Doc {
pub fn new(valid_idents: Vec<String>) -> Self {
- Doc { valid_idents: valid_idents }
+ Self { valid_idents: valid_idents }
}
}
}
impl<'a> Parser<'a> {
- fn new(parser: pulldown_cmark::Parser<'a>) -> Parser<'a> {
- Self { parser }
+ fn new(parser: pulldown_cmark::Parser<'a>) -> Self {
+ Self { parser: parser }
}
}
/// Cleanup documentation decoration (`///` and such).
///
/// We can't use `syntax::attr::AttributeMethods::with_desugared_doc` or
-/// `syntax::parse::lexer::comments::strip_doc_comment_decoration` because we need to keep track of
+/// `syntax::parse::lexer::comments::strip_doc_comment_decoration` because we
+/// need to keep track of
/// the spans but this function is inspired from the later.
#[allow(cast_possible_truncation)]
pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<(usize, Span)>) {
doc.push('\n');
return (
doc.to_owned(),
- vec![(doc.len(), Span { lo: span.lo + BytePos(prefix.len() as u32), ..span })]
+ vec![
+ (doc.len(), span.with_lo(span.lo() + BytePos(prefix.len() as u32))),
+ ],
);
}
}
if comment.starts_with("/*") {
let doc = &comment[3..comment.len() - 2];
let mut sizes = vec![];
-
+ let mut contains_initial_stars = false;
for line in doc.lines() {
let offset = line.as_ptr() as usize - comment.as_ptr() as usize;
debug_assert_eq!(offset as u32 as usize, offset);
-
+ contains_initial_stars |= line.trim_left().starts_with('*');
// +1 for the newline
- sizes.push((line.len()+1, Span { lo: span.lo + BytePos(offset as u32), ..span }));
+ sizes.push((line.len() + 1, span.with_lo(span.lo() + BytePos(offset as u32))));
}
-
- return (doc.to_string(), sizes);
+ if !contains_initial_stars {
+ return (doc.to_string(), sizes);
+ }
+ // remove the initial '*'s if any
+ let mut no_stars = String::with_capacity(doc.len());
+ for line in doc.lines() {
+ let mut chars = line.chars();
+ while let Some(c) = chars.next() {
+ if c.is_whitespace() {
+ no_stars.push(c);
+ } else {
+ no_stars.push(if c == '*' { ' ' } else { c });
+ break;
+ }
+ }
+ no_stars.push_str(chars.as_str());
+ no_stars.push('\n');
+ }
+ return (no_stars, sizes);
}
panic!("not a doc-comment: {}", comment);
let mut x = x.into_owned();
x.push_str(&y);
Ok((x_offset, Text(x.into())))
- }
+ },
(x, y) => Err(((x_offset, x), (y_offset, y))),
}
});
}
}
-fn check_doc<'a, Events: Iterator<Item=(usize, pulldown_cmark::Event<'a>)>>(
+fn check_doc<'a, Events: Iterator<Item = (usize, pulldown_cmark::Event<'a>)>>(
cx: &EarlyContext,
valid_idents: &[String],
docs: Events,
- spans: &[(usize, Span)]
+ spans: &[(usize, Span)],
) {
use pulldown_cmark::Event::*;
use pulldown_cmark::Tag::*;
for (offset, event) in docs {
match event {
- Start(CodeBlock(_)) | Start(Code) => in_code = true,
- End(CodeBlock(_)) | End(Code) => in_code = false,
+ Start(CodeBlock(_)) |
+ Start(Code) => in_code = true,
+ End(CodeBlock(_)) |
+ End(Code) => in_code = false,
Start(_tag) | End(_tag) => (), // We don't care about other tags
- Html(_html) | InlineHtml(_html) => (), // HTML is weird, just ignore it
+ Html(_html) |
+ InlineHtml(_html) => (), // HTML is weird, just ignore it
SoftBreak => (),
HardBreak => (),
- FootnoteReference(text) | Text(text) => {
+ FootnoteReference(text) |
+ Text(text) => {
if !in_code {
let index = match spans.binary_search_by(|c| c.0.cmp(&offset)) {
Ok(o) => o,
- Err(e) => e-1,
+ Err(e) => e - 1,
};
let (begin, span) = spans[index];
// Adjust for the begining of the current `Event`
- let span = Span {
- lo: span.lo + BytePos::from_usize(offset - begin),
- ..span
- };
+ let span = span.with_lo(span.lo() + BytePos::from_usize(offset - begin));
check_text(cx, valid_idents, &text, span);
}
// Adjust for the current word
let offset = word.as_ptr() as usize - text.as_ptr() as usize;
- let span = Span {
- lo: span.lo + BytePos::from_usize(offset),
- hi: span.lo + BytePos::from_usize(offset + word.len()),
- ..span
- };
+ let span = Span::new(
+ span.lo() + BytePos::from_usize(offset),
+ span.lo() + BytePos::from_usize(offset + word.len()),
+ span.ctxt(),
+ );
check_word(cx, word, span);
}
}
fn check_word(cx: &EarlyContext, word: &str, span: Span) {
- /// Checks if a string is camel-case, ie. contains at least two uppercase letter (`Clippy` is
- /// ok) and one lower-case letter (`NASA` is ok). Plural are also excluded (`IDs` is ok).
+ /// Checks if a string is camel-case, ie. contains at least two uppercase
+ /// letter (`Clippy` is
+ /// ok) and one lower-case letter (`NASA` is ok). Plural are also excluded
+ /// (`IDs` is ok).
fn is_camel_case(s: &str) -> bool {
if s.starts_with(|c: char| c.is_digit(10)) {
return false;
};
s.chars().all(char::is_alphanumeric) && s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1 &&
- s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0
+ s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0
}
fn has_underscore(s: &str) -> bool {
}
if has_underscore(word) || word.contains("::") || is_camel_case(word) {
- span_lint(cx,
- DOC_MARKDOWN,
- span,
- &format!("you should put `{}` between ticks in the documentation", word));
+ span_lint(
+ cx,
+ DOC_MARKDOWN,
+ span,
+ &format!("you should put `{}` between ticks in the documentation", word),
+ );
}
}