From b63d66fc3e938eaa4cffc34f21f38f2f6f4a27e7 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sat, 20 Aug 2022 13:37:21 -0400 Subject: [PATCH] Add settings hash to cache (#20) --- src/bin/rust_python_linter.rs | 2 +- src/cache.rs | 20 +++++++++++++------- src/check_ast.rs | 9 +++++---- src/checks.rs | 2 +- src/linter.rs | 16 ++++++++-------- src/pyproject.rs | 12 ++++++------ src/settings.rs | 18 ++++++++++++++---- 7 files changed, 48 insertions(+), 31 deletions(-) diff --git a/src/bin/rust_python_linter.rs b/src/bin/rust_python_linter.rs index aeddb52f39..526225b996 100644 --- a/src/bin/rust_python_linter.rs +++ b/src/bin/rust_python_linter.rs @@ -95,7 +95,7 @@ fn main() -> Result<()> { set_up_logging(cli.verbose)?; - // TODO(charlie): Avoid this cast. + // TODO(charlie): Can we avoid this cast? let paths: Vec<&Path> = cli.files.iter().map(PathBuf::as_path).collect(); let settings = Settings::from_paths(paths)?; diff --git a/src/cache.rs b/src/cache.rs index 9b45f329a9..6a0c6fdb57 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -1,3 +1,5 @@ +use std::collections::hash_map::DefaultHasher; +use std::hash::{Hash, Hasher}; use std::os::unix::fs::MetadataExt; use std::path::Path; @@ -6,6 +8,7 @@ use log::error; use serde::{Deserialize, Serialize}; use crate::message::Message; +use crate::settings::Settings; const VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -67,20 +70,23 @@ fn cache_dir() -> &'static str { "./.cache" } -fn cache_key(path: &Path) -> String { +fn cache_key(path: &Path, settings: &Settings) -> String { + let mut hasher = DefaultHasher::new(); + settings.hash(&mut hasher); format!( - "{}@{}", + "{}@{}@{}", path.canonicalize().unwrap().to_string_lossy(), - VERSION + VERSION, + hasher.finish() ) } -pub fn get(path: &Path, mode: &Mode) -> Option> { +pub fn get(path: &Path, settings: &Settings, mode: &Mode) -> Option> { if !mode.allow_read() { return None; }; - match cacache::read_sync(cache_dir(), cache_key(path)) { + match cacache::read_sync(cache_dir(), cache_key(path, settings)) { Ok(encoded) => match path.metadata() { Ok(m) => match bincode::deserialize::(&encoded[..]) { Ok(CheckResult { metadata, messages }) => { @@ -98,7 +104,7 @@ pub fn get(path: &Path, mode: &Mode) -> Option> { None } -pub fn set(path: &Path, messages: &[Message], mode: &Mode) { +pub fn set(path: &Path, settings: &Settings, messages: &[Message], mode: &Mode) { if !mode.allow_write() { return; }; @@ -113,7 +119,7 @@ pub fn set(path: &Path, messages: &[Message], mode: &Mode) { }; if let Err(e) = cacache::write_sync( cache_dir(), - cache_key(path), + cache_key(path, settings), bincode::serialize(&check_result).unwrap(), ) { error!("Failed to write to cache: {e:?}") diff --git a/src/check_ast.rs b/src/check_ast.rs index fdb570a712..8b4ee205f0 100644 --- a/src/check_ast.rs +++ b/src/check_ast.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use std::collections::BTreeSet; use rustpython_parser::ast::{Arg, Arguments, Expr, ExprKind, Stmt, StmtKind, Suite}; @@ -99,7 +99,7 @@ impl Visitor for Checker<'_> { } // Search for duplicates. - let mut idents: HashSet = HashSet::new(); + let mut idents: BTreeSet = BTreeSet::new(); for arg in all_arguments { let ident = &arg.node.arg; if idents.contains(ident) { @@ -130,8 +130,9 @@ pub fn check_ast(python_ast: &Suite, settings: &Settings) -> Vec { #[cfg(test)] mod tests { + use std::collections::BTreeSet; + use rustpython_parser::ast::{Alias, Location, Stmt, StmtKind}; - use std::collections::HashSet; use crate::check_ast::Checker; use crate::checks::CheckKind::ImportStarUsage; @@ -144,7 +145,7 @@ mod tests { let settings = Settings { line_length: 88, exclude: vec![], - select: HashSet::from([CheckCode::F403]), + select: BTreeSet::from([CheckCode::F403]), }; let mut checker = Checker::new(&settings); checker.visit_stmt(&Stmt { diff --git a/src/checks.rs b/src/checks.rs index 59b6ad92e7..b5d49ca7e7 100644 --- a/src/checks.rs +++ b/src/checks.rs @@ -1,7 +1,7 @@ use rustpython_parser::ast::Location; use serde::{Deserialize, Serialize}; -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Hash)] +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Hash, PartialOrd, Ord)] pub enum CheckCode { F831, F541, diff --git a/src/linter.rs b/src/linter.rs index 8cf773fc49..a5be15f7f6 100644 --- a/src/linter.rs +++ b/src/linter.rs @@ -13,7 +13,7 @@ use crate::{cache, fs}; pub fn check_path(path: &Path, settings: &Settings, mode: &cache::Mode) -> Result> { // Check the cache. - if let Some(messages) = cache::get(path, mode) { + if let Some(messages) = cache::get(path, settings, mode) { debug!("Cache hit for: {}", path.to_string_lossy()); return Ok(messages); } @@ -53,14 +53,14 @@ pub fn check_path(path: &Path, settings: &Settings, mode: &cache::Mode) -> Resul }) .filter(|message| !message.is_inline_ignored()) .collect(); - cache::set(path, &messages, mode); + cache::set(path, settings, &messages, mode); Ok(messages) } #[cfg(test)] mod tests { - use std::collections::HashSet; + use std::collections::BTreeSet; use std::path::Path; use anyhow::Result; @@ -81,7 +81,7 @@ mod tests { &settings::Settings { line_length: 88, exclude: vec![], - select: HashSet::from([CheckCode::F831]), + select: BTreeSet::from([CheckCode::F831]), }, &cache::Mode::None, )?; @@ -117,7 +117,7 @@ mod tests { &settings::Settings { line_length: 88, exclude: vec![], - select: HashSet::from([CheckCode::F541]), + select: BTreeSet::from([CheckCode::F541]), }, &cache::Mode::None, )?; @@ -153,7 +153,7 @@ mod tests { &settings::Settings { line_length: 88, exclude: vec![], - select: HashSet::from([CheckCode::F634]), + select: BTreeSet::from([CheckCode::F634]), }, &cache::Mode::None, )?; @@ -184,7 +184,7 @@ mod tests { &settings::Settings { line_length: 88, exclude: vec![], - select: HashSet::from([CheckCode::F403]), + select: BTreeSet::from([CheckCode::F403]), }, &cache::Mode::None, )?; @@ -215,7 +215,7 @@ mod tests { &settings::Settings { line_length: 88, exclude: vec![], - select: HashSet::from([CheckCode::E501]), + select: BTreeSet::from([CheckCode::E501]), }, &cache::Mode::None, )?; diff --git a/src/pyproject.rs b/src/pyproject.rs index 8e7dbf94f1..d69ac72e68 100644 --- a/src/pyproject.rs +++ b/src/pyproject.rs @@ -1,12 +1,12 @@ -use std::collections::HashSet; +use std::collections::BTreeSet; use std::path::{Path, PathBuf}; -use crate::checks::CheckCode; use anyhow::Result; use common_path::common_path_all; use log::debug; use serde::Deserialize; +use crate::checks::CheckCode; use crate::fs; pub fn load_config<'a>(paths: impl IntoIterator) -> Result<(PathBuf, Config)> { @@ -32,7 +32,7 @@ pub fn load_config<'a>(paths: impl IntoIterator) -> Result<(Pat pub struct Config { pub line_length: Option, pub exclude: Option>, - pub select: Option>, + pub select: Option>, } #[derive(Debug, PartialEq, Eq, Deserialize)] @@ -85,12 +85,12 @@ fn find_project_root<'a>(sources: impl IntoIterator) -> Option< #[cfg(test)] mod tests { - use std::collections::HashSet; + use std::collections::BTreeSet; use std::path::Path; - use crate::checks::CheckCode; use anyhow::Result; + use crate::checks::CheckCode; use crate::pyproject::{ find_project_root, find_pyproject_toml, parse_pyproject_toml, Config, PyProject, Tools, }; @@ -173,7 +173,7 @@ select = ["E501"] linter: Some(Config { line_length: None, exclude: None, - select: Some(HashSet::from([CheckCode::E501])), + select: Some(BTreeSet::from([CheckCode::E501])), }) }) ); diff --git a/src/settings.rs b/src/settings.rs index 0ebf251627..232bd8d523 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -1,15 +1,25 @@ -use std::collections::HashSet; +use std::collections::BTreeSet; +use std::hash::{Hash, Hasher}; use std::path::{Path, PathBuf}; -use crate::checks::CheckCode; use anyhow::Result; +use crate::checks::CheckCode; use crate::pyproject::load_config; pub struct Settings { pub line_length: usize, pub exclude: Vec, - pub select: HashSet, + pub select: BTreeSet, +} + +impl Hash for Settings { + fn hash(&self, state: &mut H) { + self.line_length.hash(state); + for value in self.select.iter() { + value.hash(state); + } + } } impl Settings { @@ -30,7 +40,7 @@ impl Settings { }) .collect(), select: config.select.unwrap_or_else(|| { - HashSet::from([ + BTreeSet::from([ CheckCode::F831, CheckCode::F541, CheckCode::F634,