diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fd2de507..068089ac 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,13 +20,17 @@ jobs: clippy: name: Clippy check runs-on: ubuntu-latest + env: + RUSTFLAGS: --deny warnings steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: components: clippy - uses: Swatinem/rust-cache@v2 - - run: cargo clippy --all-targets --all-features -- --deny warnings + - run: cargo clippy --all-targets --all-features + - run: cargo clippy --all-targets + - run: cargo clippy --all-targets --no-default-features test: name: Test code diff --git a/scraper/Cargo.toml b/scraper/Cargo.toml index 4d85bfde..0e64a53a 100644 --- a/scraper/Cargo.toml +++ b/scraper/Cargo.toml @@ -34,6 +34,25 @@ atomic = [] errors = [] serde = ["dep:serde"] +[lints.rust] +missing_copy_implementations = "warn" +missing_debug_implementations = "warn" +redundant_imports = "warn" +single_use_lifetimes = "warn" +trivial_casts = "warn" +trivial_numeric_casts = "warn" +unused_extern_crates = "warn" +unused_import_braces = "warn" +unused_qualifications = "warn" +variant_size_differences = "warn" +[lints.clippy] +pedantic = { level = "warn", priority = -1 } +allow_attributes = "warn" + +missing_errors_doc = "allow" +missing_panics_doc = "allow" +must_use_candidate = "allow" + [[bin]] name = "scraper" path = "src/main.rs" diff --git a/scraper/examples/document.rs b/scraper/examples/document.rs index e9bd9d1c..92b71a5a 100644 --- a/scraper/examples/document.rs +++ b/scraper/examples/document.rs @@ -1,5 +1,3 @@ -extern crate scraper; - use std::io::{self, Read, Write}; use scraper::{Html, Selector}; diff --git a/scraper/examples/fragment.rs b/scraper/examples/fragment.rs index dff98506..e1c531c2 100644 --- a/scraper/examples/fragment.rs +++ b/scraper/examples/fragment.rs @@ -1,5 +1,3 @@ -extern crate scraper; - use std::io::{self, Read, Write}; use scraper::{Html, Selector}; diff --git a/scraper/src/element_ref/mod.rs b/scraper/src/element_ref/mod.rs index b00dd8f2..d8534bf9 100644 --- a/scraper/src/element_ref/mod.rs +++ b/scraper/src/element_ref/mod.rs @@ -49,7 +49,7 @@ impl<'a> ElementRef<'a> { scope: *self, inner, selector, - caches: Default::default(), + caches: SelectorCaches::default(), } } @@ -154,7 +154,7 @@ impl Clone for Select<'_, '_> { scope: self.scope, inner: self.inner.clone(), selector: self.selector, - caches: Default::default(), + caches: SelectorCaches::default(), } } } diff --git a/scraper/src/html/mod.rs b/scraper/src/html/mod.rs index 0722c693..983fac24 100644 --- a/scraper/src/html/mod.rs +++ b/scraper/src/html/mod.rs @@ -76,8 +76,10 @@ impl Html { /// # } /// ``` pub fn parse_document(document: &str) -> Self { - let parser = - driver::parse_document(HtmlTreeSink::new(Self::new_document()), Default::default()); + let parser = driver::parse_document( + HtmlTreeSink::new(Self::new_document()), + ParseOpts::default(), + ); parser.one(document) } @@ -100,7 +102,7 @@ impl Html { Select { inner: self.tree.nodes(), selector, - caches: Default::default(), + caches: SelectorCaches::default(), } } @@ -149,7 +151,7 @@ impl Clone for Select<'_, '_> { Self { inner: self.inner.clone(), selector: self.selector, - caches: Default::default(), + caches: SelectorCaches::default(), } } } diff --git a/scraper/src/html/tree_sink.rs b/scraper/src/html/tree_sink.rs index 10136ec9..7aefd41d 100644 --- a/scraper/src/html/tree_sink.rs +++ b/scraper/src/html/tree_sink.rs @@ -217,9 +217,8 @@ impl TreeSink for HtmlTreeSink { fn add_attrs_if_missing(&self, target: &Self::Handle, attrs: Vec) { let mut this = self.0.borrow_mut(); let mut node = this.tree.get_mut(*target).unwrap(); - let element = match *node.value() { - Node::Element(ref mut e) => e, - _ => unreachable!(), + let Node::Element(ref mut element) = *node.value() else { + unreachable!() }; for attr in attrs { @@ -289,9 +288,9 @@ impl TreeSink for HtmlTreeSink { .is_some(); if has_parent { - self.append_before_sibling(element, child) + self.append_before_sibling(element, child); } else { - self.append(prev_element, child) + self.append(prev_element, child); } } } diff --git a/scraper/src/lib.rs b/scraper/src/lib.rs index be354b1b..62b1170b 100644 --- a/scraper/src/lib.rs +++ b/scraper/src/lib.rs @@ -1,15 +1,5 @@ #![doc = include_str!("../README.md")] -#![warn( - missing_docs, - missing_debug_implementations, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unused_extern_crates, - unused_import_braces, - unused_qualifications, - variant_size_differences -)] +#![warn(missing_docs)] //! # The core types //! diff --git a/scraper/src/main.rs b/scraper/src/main.rs index 72328670..a90500a6 100644 --- a/scraper/src/main.rs +++ b/scraper/src/main.rs @@ -1,6 +1,3 @@ -extern crate getopts; -extern crate scraper; - use getopts::Options; use scraper::{Html, Selector}; use std::env; @@ -36,9 +33,9 @@ fn query(input: &Input, output: &Output, selector: &Selector, file: &mu Input::Fragment => Html::parse_fragment(&html), }; - let mut matched = false; + let mut has_matches = false; for element in html.select(selector) { - use crate::Output::*; + use crate::Output::{Attr, Classes, Html, Id, InnerHtml, Name, Text}; match *output { Html => println!("{}", element.html()), InnerHtml => println!("{}", element.inner_html()), @@ -51,9 +48,9 @@ fn query(input: &Input, output: &Output, selector: &Selector, file: &mu Name => println!("{}", element.value().name()), Text => println!("{}", element.text().collect::()), } - matched = true; + has_matches = true; } - matched + has_matches } fn main() { @@ -135,7 +132,7 @@ fn main() { process::exit(USAGE); }); - let matched = if files.is_empty() { + let selector_has_matches = if files.is_empty() { query(&input, &output, &selector, &mut io::stdin()) } else { files @@ -145,5 +142,5 @@ fn main() { .any(|mut f| query(&input, &output, &selector, &mut f)) }; - process::exit(i32::from(!matched)); + process::exit(i32::from(!selector_has_matches)); } diff --git a/scraper/src/node.rs b/scraper/src/node.rs index a1c45af0..ee5d74c1 100644 --- a/scraper/src/node.rs +++ b/scraper/src/node.rs @@ -11,7 +11,6 @@ use std::cell::OnceCell; /// An HTML node. // `Element` is usally the most common variant and hence boxing it // will most likely not improve performance overall. -#[allow(variant_size_differences)] #[derive(Clone, PartialEq, Eq)] pub enum Node { /// The document root. @@ -139,17 +138,17 @@ pub struct Doctype { impl Doctype { /// Returns the doctype name. pub fn name(&self) -> &str { - self.name.deref() + &self.name } /// Returns the doctype public ID. pub fn public_id(&self) -> &str { - self.public_id.deref() + &self.public_id } /// Returns the doctype system ID. pub fn system_id(&self) -> &str { - self.system_id.deref() + &self.system_id } } @@ -182,7 +181,7 @@ impl Deref for Comment { impl fmt::Debug for Comment { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "", self.deref()) + write!(f, "", &**self) } } @@ -203,7 +202,7 @@ impl Deref for Text { impl fmt::Debug for Text { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "{:?}", self.deref()) + write!(f, "{:?}", &**self) } } @@ -240,7 +239,7 @@ pub struct Element { impl Element { #[doc(hidden)] pub fn new(name: QualName, attributes: Vec) -> Self { - #[allow(unused_mut)] + #[cfg_attr(feature = "deterministic", expect(unused_mut))] let mut attrs = attributes .into_iter() .map(|attr| (attr.name, crate::tendril_util::make(attr.value))) @@ -259,7 +258,7 @@ impl Element { /// Returns the element name. pub fn name(&self) -> &str { - self.name.local.deref() + &self.name.local } /// Returns the element ID. @@ -327,7 +326,7 @@ impl Element { } /// Iterator over classes. -#[allow(missing_debug_implementations)] +#[expect(missing_debug_implementations)] #[derive(Clone)] pub struct Classes<'a> { inner: SliceIter<'a, LocalName>, @@ -350,7 +349,7 @@ pub type AttributesIter<'a> = indexmap::map::Iter<'a, QualName, StrTendril>; pub type AttributesIter<'a> = SliceIter<'a, (QualName, StrTendril)>; /// Iterator over attributes. -#[allow(missing_debug_implementations)] +#[expect(missing_debug_implementations)] #[derive(Clone)] pub struct Attrs<'a> { inner: AttributesIter<'a>, @@ -360,7 +359,7 @@ impl<'a> Iterator for Attrs<'a> { type Item = (&'a str, &'a str); fn next(&mut self) -> Option<(&'a str, &'a str)> { - self.inner.next().map(|(k, v)| (k.local.deref(), v.deref())) + self.inner.next().map(|(k, v)| (&*k.local, &**v)) } } diff --git a/scraper/src/node/serializable.rs b/scraper/src/node/serializable.rs index 724dedf2..30b84706 100644 --- a/scraper/src/node/serializable.rs +++ b/scraper/src/node/serializable.rs @@ -6,6 +6,10 @@ use html5ever::serialize::{Serializer, TraversalScope}; use crate::Node; /// Serialize an HTML node using html5ever serializer. +#[expect( + clippy::needless_pass_by_value, + reason = "same as html5ever Serialize trait" +)] pub(crate) fn serialize( self_node: NodeRef, serializer: &mut S, diff --git a/scraper/src/selector.rs b/scraper/src/selector.rs index ab3605d0..0be37a6c 100644 --- a/scraper/src/selector.rs +++ b/scraper/src/selector.rs @@ -1,6 +1,5 @@ //! CSS selectors. -use std::convert::TryFrom; use std::fmt; use std::str::FromStr; @@ -46,7 +45,7 @@ impl Selector { /// The optional `scope` argument is used to specify which element has `:scope` pseudo-class. /// When it is `None`, `:scope` will match the root element. pub fn matches_with_scope(&self, element: &ElementRef, scope: Option) -> bool { - self.matches_with_scope_and_cache(element, scope, &mut Default::default()) + self.matches_with_scope_and_cache(element, scope, &mut matching::SelectorCaches::default()) } // The `nth_index_cache` must not be used after `self` is dropped @@ -116,7 +115,7 @@ impl Visitor<'_> for SelectorVisitor { /// An implementation of `Parser` for `selectors` #[derive(Clone, Copy, Debug)] pub struct Parser; -impl<'i> parser::Parser<'i> for Parser { +impl parser::Parser<'_> for Parser { type Impl = Simple; type Error = SelectorParseErrorKind; @@ -256,7 +255,6 @@ impl FromStr for Selector { #[cfg(test)] mod tests { use super::*; - use std::convert::TryInto; #[test] fn selector_conversions() { @@ -268,7 +266,7 @@ mod tests { } #[test] - #[should_panic] + #[should_panic = "UnexpectedSelectorParseError"] fn invalid_selector_conversions() { let s = ""; let _sel: Selector = s.try_into().unwrap();