#![warn(
clippy::all,
clippy::pedantic,
clippy::restriction,
clippy::nursery,
clippy::cargo
)]
#![allow(
// Group of too restrictive lints
clippy::integer_arithmetic,
clippy::float_arithmetic,
clippy::blanket_clippy_restriction_lints,
clippy::implicit_return,
clippy::enum_glob_use,
clippy::wildcard_enum_match_arm,
clippy::pattern_type_mismatch,
clippy::shadow_reuse,
clippy::shadow_same,
clippy::shadow_unrelated,
clippy::must_use_candidate,
clippy::clone_on_ref_ptr,
clippy::multiple_crate_versions,
clippy::default_numeric_fallback,
clippy::map_err_ignore,
clippy::pub_use,
clippy::format_push_string,
// We decided that we're ok with expect
clippy::expect_used,
// Too restrictive for the current style
clippy::missing_inline_in_public_items,
clippy::exhaustive_structs,
clippy::exhaustive_enums,
clippy::module_name_repetitions,
clippy::unseparated_literal_suffix,
clippy::self_named_module_files,
// Currently breaks CI, let's wait a bit more until new clippy version is more spread.
// clippy::single_char_lifetime_names,
// Allowed lints related to cargo
// (comment these out if you'd like to improve Cargo.toml)
clippy::wildcard_dependencies,
clippy::redundant_feature_names,
clippy::cargo_common_metadata,
// Comment these out when writing docs
clippy::missing_docs_in_private_items,
clippy::missing_errors_doc,
// Comment these out before submitting a PR
clippy::todo,
clippy::panic_in_result_fn,
clippy::panic,
clippy::unimplemented,
clippy::unreachable,
clippy::negative_feature_names
)]
use harriet::TurtleDocument;
use lint::LintResult;
use lints::{LintSet, PlowLint};
use plow_graphify::document_to_graph;
use field33_rdftk_core_temporary_fork::model::graph::GraphRef;
pub mod lint;
pub mod lints;
#[cfg_attr(doc, aquamarine::aquamarine)]
#[cfg_attr(doc, aquamarine::aquamarine)]
pub const fn doc_process() {}
#[allow(clippy::undocumented_unsafe_blocks)]
unsafe impl Sync for MultiReaderRdfGraph {}
pub struct MultiReaderRdfGraph {
pub inner: GraphRef,
}
pub struct Linter<'linter> {
document: TurtleDocument<'linter>,
graph: MultiReaderRdfGraph,
lints: Vec<LintSet>,
}
impl<'linter> TryFrom<&'linter str> for Linter<'linter> {
type Error = anyhow::Error;
fn try_from(field_contents: &'linter str) -> Result<Self, Self::Error> {
let document = TurtleDocument::parse_full(field_contents)
.map_err(|_| anyhow::anyhow!("Parse error."))?;
let graph = document_to_graph(&document)?;
let multi_reader_graph = MultiReaderRdfGraph { inner: graph };
Ok(Self {
document,
graph: multi_reader_graph,
lints: vec![],
})
}
}
impl Linter<'_> {
pub fn add_lint_as_set(
&mut self,
lints: Vec<PlowLint>,
sub_lints: Option<Vec<PlowLint>>,
) -> uuid::Uuid {
let id = uuid::Uuid::new_v4();
let set = LintSet {
id,
description: "injected lint".to_owned(),
lints,
sub_lints,
};
self.lints.push(set);
id
}
pub fn add_lint_set(&mut self, lint_set: LintSet) -> String {
let description = String::from(&lint_set.description);
self.lints.push(lint_set);
description
}
pub fn remove_all_lints(&mut self) {
self.lints.clear();
}
}
impl Linter<'_> {
pub fn run_all_lints(&self) -> Vec<LintResult> {
let results = self.lints.iter().fold(vec![], |mut results, lint_set| {
let set_results = lint_set.lints.iter().fold(vec![], |mut set_results, lint| {
let result = lint.run(self);
set_results.push(result);
set_results
});
results.extend(set_results);
results
});
results
}
pub fn run_lint_set(&self, id: uuid::Uuid) -> Vec<LintResult> {
let set_results = self.lints.iter().fold(vec![], |set_results, lint_set| {
if lint_set.id == id {
let set_results = lint_set.lints.iter().fold(vec![], |mut set_results, lint| {
let result = lint.run(self);
set_results.push(result);
set_results
});
return set_results;
}
set_results
});
set_results
}
pub fn run_lints_check_if_contains_any_failure(&self) -> bool {
self.lints.iter().any(|lint_set| {
lint_set
.lints
.iter()
.any(|lint| lint.run(self).is_failure())
})
}
}