diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12b8f856..8daa482d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,10 @@ on: branches: - main + schedule: + # run every morning at 10am Pacific Time + - cron: '0 17 * * *' + name: ci env: @@ -15,7 +19,7 @@ env: RUST_BACKTRACE: 1 # Pin the nightly toolchain to prevent breakage. # This should be occasionally updated. - RUST_NIGHTLY_TOOLCHAIN: nightly-2023-10-06 + RUST_NIGHTLY_TOOLCHAIN: nightly-2024-10-07 jobs: env: diff --git a/Cargo.toml b/Cargo.toml index 1831ff10..e041bc58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,10 +17,10 @@ fnv = { version = "1", default-features = false } glob = "0.3" lazy_static = "1" pathdiff = "0.2" -pulldown-cmark = { version = "0.9", default-features = false } +pulldown-cmark = { version = "0.12", default-features = false } rayon = "1" regex = "1" -reqwest = { version = "0.11", features = ["blocking", "native-tls"] } +reqwest = { version = "0.12", features = ["blocking", "native-tls"] } serde = { version = "1", features = ["derive"] } slug = { version = "0.1" } structopt = "0.3" diff --git a/rust-toolchain b/rust-toolchain index 902c7418..dbd41264 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.65.0 +1.81.0 diff --git a/src/extract.rs b/src/extract.rs index e716daac..ae29fd9b 100644 --- a/src/extract.rs +++ b/src/extract.rs @@ -124,7 +124,7 @@ fn extract_sections<'a>(spec: &'a Specification) -> Vec<(&'a Section<'a>, Vec(section: &'a Section<'a>) -> (&'a Section<'a>, Vec) { +fn extract_section<'a>(section: &'a Section<'a>) -> (&'a Section<'a>, Vec>) { let mut features = vec![]; let lines = §ion.lines[..]; @@ -204,7 +204,7 @@ pub struct Feature<'a> { quote: Vec<&'a str>, } -impl<'a> Feature<'a> { +impl Feature<'_> { pub fn should_add(&self) -> bool { match self.compound_level() { Some(level) => level == self.level, diff --git a/src/parser.rs b/src/parser.rs index 74fe8a15..008aa452 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -119,7 +119,7 @@ impl<'a> From> for Annotation { } } -impl<'a> Iterator for Parser<'a> { +impl Iterator for Parser<'_> { type Item = Result; fn next(&mut self) -> Option { diff --git a/src/pattern.rs b/src/pattern.rs index 8d34aff2..5f56f471 100644 --- a/src/pattern.rs +++ b/src/pattern.rs @@ -19,7 +19,7 @@ pub struct Pattern<'a> { content: &'a str, } -impl<'a> Default for Pattern<'a> { +impl Default for Pattern<'_> { fn default() -> Self { Self { meta: "//=", diff --git a/src/report/mod.rs b/src/report/mod.rs index e56df62b..58d73b8e 100644 --- a/src/report/mod.rs +++ b/src/report/mod.rs @@ -72,7 +72,7 @@ enum ReportError<'a> { MissingSection { annotation: &'a Annotation }, } -impl<'a> fmt::Display for ReportError<'a> { +impl fmt::Display for ReportError<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Self::QuoteMismatch { annotation } => write!( @@ -301,7 +301,7 @@ pub struct TargetReport<'a> { statuses: status::StatusMap, } -impl<'a> TargetReport<'a> { +impl TargetReport<'_> { #[allow(dead_code)] pub fn statistics(&self) -> Statistics { let mut stats = Statistics::default(); diff --git a/src/source.rs b/src/source.rs index 0bbc8fa0..4c6aafc5 100644 --- a/src/source.rs +++ b/src/source.rs @@ -17,7 +17,7 @@ pub enum SourceFile<'a> { Spec(PathBuf), } -impl<'a> SourceFile<'a> { +impl SourceFile<'_> { pub fn annotations(&self) -> Result { let mut annotations = AnnotationSet::new(); match self { @@ -73,7 +73,7 @@ struct Spec<'a> { quote: &'a str, } -impl<'a> Spec<'a> { +impl Spec<'_> { fn into_annotation( self, source: PathBuf, @@ -119,7 +119,7 @@ struct Exception<'a> { reason: String, } -impl<'a> Exception<'a> { +impl Exception<'_> { fn into_annotation( self, source: PathBuf, @@ -162,7 +162,7 @@ struct Todo<'a> { tags: BTreeSet, } -impl<'a> Todo<'a> { +impl Todo<'_> { fn into_annotation( self, source: PathBuf, diff --git a/src/sourcemap.rs b/src/sourcemap.rs index b26738c3..1c472262 100644 --- a/src/sourcemap.rs +++ b/src/sourcemap.rs @@ -63,13 +63,13 @@ pub struct Str<'a> { pub line: usize, } -impl<'a> fmt::Display for Str<'a> { +impl fmt::Display for Str<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.value.fmt(f) } } -impl<'a> Str<'a> { +impl Str<'_> { pub fn indentation(&self) -> usize { let trimmed_line = self.trim_start(); self.len() - trimmed_line.len() @@ -126,7 +126,7 @@ impl<'a> Str<'a> { } } -impl<'a> Deref for Str<'a> { +impl Deref for Str<'_> { type Target = str; fn deref(&self) -> &str { diff --git a/src/specification/ietf.rs b/src/specification/ietf.rs index cd79a689..7122d28b 100644 --- a/src/specification/ietf.rs +++ b/src/specification/ietf.rs @@ -41,7 +41,7 @@ pub enum ParserState<'a> { Section { section: Section<'a>, indent: usize }, } -impl<'a> Default for ParserState<'a> { +impl Default for ParserState<'_> { fn default() -> Self { Self::Init } @@ -105,7 +105,7 @@ impl<'a> Parser<'a> { if let Some(section) = section_header(line) { self.state = ParserState::Section { section, - indent: core::usize::MAX, + indent: usize::MAX, }; } } @@ -132,7 +132,7 @@ impl<'a> Parser<'a> { self.on_section(section, indent); self.state = ParserState::Section { section: new_section, - indent: core::usize::MAX, + indent: usize::MAX, }; } else { // most likely the footer/header diff --git a/src/specification/markdown.rs b/src/specification/markdown.rs index 4805dd64..723337ba 100644 --- a/src/specification/markdown.rs +++ b/src/specification/markdown.rs @@ -37,7 +37,7 @@ enum Token<'a> { struct Lex<'a> { contents: &'a str, lines: Peekable>, - cmark: Peekable>, + cmark: Peekable>, next_line: Option>, next_token: Option>, } @@ -69,7 +69,7 @@ impl<'a> Iterator for Lex<'a> { type Item = Token<'a>; fn next(&mut self) -> Option { - use pulldown_cmark::{Event::*, HeadingLevel::*, Tag::*}; + use pulldown_cmark::{Event::*, HeadingLevel::*, Tag, TagEnd}; let mut header_buffer = None; let mut text_buffer: Option<(usize, Range)> = None; @@ -92,11 +92,13 @@ impl<'a> Iterator for Lex<'a> { }) { match event { // start buffering the header contents - Start(Heading(_, _, _)) => { - header_buffer = Some((line.line, line.range())); + Start(Tag::Heading { id, .. }) => { + // convert the fragment to a Str + let fragment = id.and_then(|f| line.substr(&f)); + header_buffer = Some((line.line, line.range(), fragment)); } // we're done parsing the header - End(Heading(level, fragment, _classes)) => { + End(TagEnd::Heading(level)) => { // consume any lines captured by the header while self .lines @@ -104,8 +106,12 @@ impl<'a> Iterator for Lex<'a> { .is_some() {} + let fragment = header_buffer + .as_ref() + .and_then(|(_, _, fragment)| *fragment); + // convert the header buffer into a Str - let line = if let Some((line_num, mut buf)) = header_buffer { + let line = if let Some((line_num, mut buf, _)) = header_buffer { let r = line.range(); buf.start = r.start.min(buf.start); buf.end = r.end.max(buf.end); @@ -114,9 +120,6 @@ impl<'a> Iterator for Lex<'a> { line }; - // convert the fragment to a Str - let fragment = fragment.and_then(|f| line.substr(f)); - // convert the text buffer range to a Str let name = if let Some((line_num, mut buf)) = text_buffer { buf.end = line.range().end.max(buf.end); @@ -142,12 +145,12 @@ impl<'a> Iterator for Lex<'a> { }); } // insert a token break before returning the line - Start(Item) => { + Start(Tag::Item) => { self.next_line = Some(line); return Some(Token::Break); } // insert a token break after returning the item line - End(Item) => { + End(TagEnd::Item) => { self.next_token = Some(Token::Break); } // buffer the text if we're parsing a header @@ -257,7 +260,7 @@ pub enum ParserState<'a> { Section { section: Section<'a>, level: u8 }, } -impl<'a> Default for ParserState<'a> { +impl Default for ParserState<'_> { fn default() -> Self { Self::Init } diff --git a/src/specification/mod.rs b/src/specification/mod.rs index 6363e990..8fcb75e2 100644 --- a/src/specification/mod.rs +++ b/src/specification/mod.rs @@ -21,7 +21,7 @@ pub struct Specification<'a> { pub format: Format, } -impl<'a> fmt::Debug for Specification<'a> { +impl fmt::Debug for Specification<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Specification") .field("title", &self.title) @@ -149,7 +149,7 @@ pub enum Line<'a> { Break, } -impl<'a> Line<'a> { +impl Line<'_> { pub fn is_empty(&self) -> bool { match self { Self::Str(s) => s.is_empty(), @@ -164,7 +164,7 @@ impl<'a> From> for Line<'a> { } } -#[derive(Clone, Debug, Eq, Hash)] +#[derive(Clone, Debug, Eq)] pub struct Section<'a> { pub id: String, pub title: String, @@ -172,7 +172,7 @@ pub struct Section<'a> { pub lines: Vec>, } -impl<'a> Ord for Section<'a> { +impl Ord for Section<'_> { fn cmp(&self, other: &Self) -> Ordering { macro_rules! cmp { ($($tt:tt)*) => { @@ -196,19 +196,28 @@ impl<'a> Ord for Section<'a> { } } -impl<'a> PartialOrd for Section<'a> { +impl core::hash::Hash for Section<'_> { + fn hash(&self, state: &mut H) { + self.id.hash(state); + self.title.hash(state); + self.full_title.hash(state); + self.lines.hash(state); + } +} + +impl PartialOrd for Section<'_> { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl<'a> PartialEq for Section<'a> { +impl PartialEq for Section<'_> { fn eq(&self, other: &Self) -> bool { self.cmp(other) == Ordering::Equal } } -impl<'a> Section<'a> { +impl Section<'_> { pub fn contents(&self) -> StrView { StrView::new(&self.lines) } @@ -276,7 +285,7 @@ pub struct StrRangeIter<'a> { end: usize, } -impl<'a> Iterator for StrRangeIter<'a> { +impl Iterator for StrRangeIter<'_> { type Item = (usize, Range); fn next(&mut self) -> Option {