Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuaclayton committed Apr 19, 2020
1 parent 699719d commit 0cae071
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 3 deletions.
4 changes: 2 additions & 2 deletions crates/cli/src/cli_configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,14 @@ impl CliConfiguration {
}
}

fn calculate_config_by_results(_results: &TokenSearchResults) -> Option<ProjectConfiguration> {
fn calculate_config_by_results(results: &TokenSearchResults) -> Option<ProjectConfiguration> {
let config_path: Option<String> = dirs::home_dir().and_then(|ref p| {
let final_path = Path::new(p).join(".unused.yml");
final_path.to_str().map(|v| v.to_owned())
});
match config_path {
Some(path) => match read_file(&path) {
Ok(contents) => ProjectConfigurations::load(&contents).get("Rails"),
Ok(contents) => ProjectConfigurations::load(&contents).best_match(results),
_ => None,
},
None => None,
Expand Down
13 changes: 12 additions & 1 deletion crates/project_configuration/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::value_assertion::Assertion;
use std::path::Path;
use token_search::TokenSearchResult;
use token_search::{TokenSearchResult, TokenSearchResults};

#[derive(Clone)]
pub struct ProjectConfiguration {
Expand All @@ -9,6 +9,7 @@ pub struct ProjectConfiguration {
pub test_file: Vec<PathPrefix>,
pub config_file: Vec<PathPrefix>,
pub low_likelihood: Vec<LowLikelihoodConfig>,
pub matches_if: Vec<Assertion>,
}

#[derive(Clone, Debug, PartialEq)]
Expand Down Expand Up @@ -44,6 +45,7 @@ impl ProjectConfiguration {
test_file: vec![PathPrefix::new("test/")],
config_file: vec![],
low_likelihood: vec![],
matches_if: vec![],
}
}

Expand All @@ -55,4 +57,13 @@ impl ProjectConfiguration {
.iter()
.find(|ll| ll.matches(token_search_result))
}

pub fn codebase_config_match(&self, results: &TokenSearchResults) -> bool {
self.matches_if.iter().all(|assertion| {
results
.value()
.iter()
.any(|result| assertion.matches(result))
})
}
}
62 changes: 62 additions & 0 deletions crates/project_configuration/src/loader.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::config::*;
use super::value_assertion::{Assertion, ValueMatcher};
use std::collections::{HashMap, HashSet};
use token_search::TokenSearchResults;
use yaml_rust::{Yaml, YamlLoader};

pub struct ProjectConfigurations {
Expand All @@ -20,6 +21,14 @@ impl ProjectConfigurations {
ProjectConfigurations { configs }
}

pub fn best_match(&self, results: &TokenSearchResults) -> Option<ProjectConfiguration> {
self.configs
.iter()
.filter(|(_, config)| config.codebase_config_match(results))
.nth(0)
.map(|(_, v)| v.clone())
}

fn parse_all_from_yaml(contents: &[Yaml]) -> HashMap<String, ProjectConfiguration> {
match contents {
[Yaml::Array(items)] => items.iter().filter(|i| !i["name"].is_badvalue()).fold(
Expand All @@ -44,6 +53,7 @@ impl ProjectConfigurations {
test_file: Self::parse_path_prefixes("test_files", contents),
config_file: Self::parse_path_prefixes("config_files", contents),
low_likelihood: Self::parse_low_likelihoods(contents),
matches_if: Self::parse_matches_if(contents),
}
}

Expand All @@ -69,15 +79,48 @@ impl ProjectConfigurations {
_ => vec![],
}
}

fn parse_matches_if(contents: &Yaml) -> Vec<Assertion> {
match &contents["matches_if"] {
Yaml::Array(items) => items
.iter()
.flat_map(|i| Self::parse_individual_matches_if(i))
.collect(),
_ => vec![],
}
}

fn parse_individual_matches_if(contents: &Yaml) -> Vec<Assertion> {
vec![
"path_starts_with",
"path_ends_with",
"path_equals",
"token_equals",
"token_starts_with",
"token_ends_with",
"allowed_tokens",
"class_or_module",
]
.iter()
.map(|&k| match &contents[k] {
Yaml::String(v) => Self::parse_single_assertion(k, &v),
_ => None,
})
.filter_map(|a| a)
.collect()
}

fn parse_low_likelihood_item(contents: &Yaml) -> Option<LowLikelihoodConfig> {
match &contents["name"] {
Yaml::String(name) => Some(LowLikelihoodConfig {
name: name.to_string(),
matchers: vec![
"path_starts_with",
"path_ends_with",
"path_equals",
"token_starts_with",
"token_ends_with",
"token_equals",
"allowed_tokens",
"class_or_module",
]
Expand Down Expand Up @@ -112,12 +155,18 @@ impl ProjectConfigurations {
"path_ends_with" => Some(Assertion::PathAssertion(ValueMatcher::EndsWith(
val.to_string(),
))),
"path_equals" => Some(Assertion::PathAssertion(ValueMatcher::Equals(
val.to_string(),
))),
"token_starts_with" => Some(Assertion::TokenAssertion(ValueMatcher::StartsWith(
val.to_string(),
))),
"token_ends_with" => Some(Assertion::TokenAssertion(ValueMatcher::EndsWith(
val.to_string(),
))),
"token_equals" => Some(Assertion::TokenAssertion(ValueMatcher::Equals(
val.to_string(),
))),
_ => None,
}
}
Expand Down Expand Up @@ -152,6 +201,10 @@ mod tests {
fn yaml_contents() -> String {
"
- name: Phoenix
matches_if:
- token_equals: Application
- token_equals: Endpoint
- token_equals: Repo
application_files:
- lib/
- web/
Expand Down Expand Up @@ -279,6 +332,15 @@ mod tests {
vec![PathPrefix::new("lib/"), PathPrefix::new("web/")]
);

assert_eq!(
phoenix_config.matches_if,
vec![
Assertion::TokenAssertion(ValueMatcher::Equals(String::from("Application"))),
Assertion::TokenAssertion(ValueMatcher::Equals(String::from("Endpoint"))),
Assertion::TokenAssertion(ValueMatcher::Equals(String::from("Repo"))),
]
);

assert_eq!(phoenix_config.test_file, vec![PathPrefix::new("test/"),]);

assert_eq!(phoenix_config.config_file, vec![PathPrefix::new("priv/"),]);
Expand Down
10 changes: 10 additions & 0 deletions crates/project_configuration/src/value_assertion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ impl Assertion {
pub enum ValueMatcher {
StartsWith(String),
EndsWith(String),
Equals(String),
ExactMatchOnAnyOf(HashSet<String>),
StartsWithCapital,
}
Expand All @@ -33,6 +34,7 @@ impl ValueMatcher {
match self {
ValueMatcher::StartsWith(v) => haystack.starts_with(v),
ValueMatcher::EndsWith(v) => haystack.ends_with(v),
ValueMatcher::Equals(v) => haystack == v,
ValueMatcher::ExactMatchOnAnyOf(vs) => vs.contains(haystack),
ValueMatcher::StartsWithCapital => haystack.starts_with(|v: char| v.is_uppercase()),
}
Expand Down Expand Up @@ -77,4 +79,12 @@ mod tests {
assert!(ValueMatcher::StartsWithCapital.check(&"Foo"));
assert!(!ValueMatcher::StartsWithCapital.check(&"foo"));
}

#[test]
fn matches_equals() {
assert!(ValueMatcher::Equals(foo()).check("foo"));
assert!(!ValueMatcher::Equals(foo()).check("Foo"));
assert!(!ValueMatcher::Equals(foo()).check(" foo"));
assert!(!ValueMatcher::Equals(foo()).check("foo "));
}
}

0 comments on commit 0cae071

Please sign in to comment.