Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for overriding project type #16

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 65 additions & 8 deletions crates/cli/src/cli_configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,40 @@ pub struct CliConfiguration {
flags: Flags,
token_search_config: TokenSearchConfig,
analysis_filter: AnalysisFilter,
project_configuration: ProjectConfiguration,
project_configuration: SelectedProjectConfiguration,
outcome: TokenUsageResults,
}

enum SelectedProjectConfiguration {
DefaultFromBestMatch(ProjectConfiguration),
DefaultFromProjectType(ProjectConfiguration, String),
ProjectType(ProjectConfiguration),
BestMatch(ProjectConfiguration),
}

impl SelectedProjectConfiguration {
pub fn project_configuration(&self) -> &ProjectConfiguration {
match self {
Self::DefaultFromBestMatch(config) => config,
Self::DefaultFromProjectType(config, _) => config,
Self::ProjectType(config) => config,
Self::BestMatch(config) => config,
}
}
}

impl CliConfiguration {
pub fn new(flags: Flags, tokens: Vec<Token>) -> Self {
let token_search_config = build_token_search_config(&flags, tokens);
let analysis_filter = build_analysis_filter(&flags);
let results = TokenSearchResults::generate_with_config(&token_search_config);
let project_configuration = load_and_parse_config()
.best_match(&results)
.unwrap_or(ProjectConfiguration::default());
let outcome =
TokenUsageResults::calculate(&token_search_config, results, &project_configuration);

let project_configuration = select_project_configuration(&flags, &results);
let outcome = TokenUsageResults::calculate(
&token_search_config,
results,
project_configuration.project_configuration(),
);

Self {
flags,
Expand Down Expand Up @@ -99,13 +119,25 @@ impl CliConfiguration {
}

pub fn configuration_name(&self) -> String {
self.project_configuration.name.to_string()
match &self.project_configuration {
SelectedProjectConfiguration::DefaultFromBestMatch(config) => {
format!("{} (unable to find a match)", config.name)
}
SelectedProjectConfiguration::DefaultFromProjectType(config, project_type) => format!(
"{} (unable to find project type '{}')",
config.name, project_type
),
SelectedProjectConfiguration::ProjectType(config) => format!("{}", config.name),
SelectedProjectConfiguration::BestMatch(config) => {
format!("{} (based on best match)", config.name)
}
}
}

pub fn low_likelihood_conflicts(&self) -> HashMap<String, Vec<AssertionConflict>> {
let mut conflict_results = HashMap::new();

for ll in self.project_configuration.low_likelihood.iter() {
for ll in self.project_configuration().low_likelihood.iter() {
let conflicts = ll.conflicts();

if conflicts.len() > 0 {
Expand All @@ -115,6 +147,10 @@ impl CliConfiguration {

conflict_results
}

pub fn project_configuration(&self) -> &ProjectConfiguration {
self.project_configuration.project_configuration()
}
}

fn build_token_search_config(cmd: &Flags, token_results: Vec<Token>) -> TokenSearchConfig {
Expand All @@ -138,6 +174,27 @@ fn build_token_search_config(cmd: &Flags, token_results: Vec<Token>) -> TokenSea
search_config
}

fn select_project_configuration(
cmd: &Flags,
results: &TokenSearchResults,
) -> SelectedProjectConfiguration {
match &cmd.project_type {
None => load_and_parse_config()
.best_match(&results)
.map(SelectedProjectConfiguration::BestMatch)
.unwrap_or(SelectedProjectConfiguration::DefaultFromBestMatch(
ProjectConfiguration::default(),
)),
Some(project_type) => load_and_parse_config()
.get(&project_type)
.map(SelectedProjectConfiguration::ProjectType)
.unwrap_or(SelectedProjectConfiguration::DefaultFromProjectType(
ProjectConfiguration::default(),
project_type.clone(),
)),
}
}

fn build_analysis_filter(cmd: &Flags) -> AnalysisFilter {
let mut analysis_filter = AnalysisFilter::default();

Expand Down
8 changes: 8 additions & 0 deletions crates/cli/src/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ pub struct Flags {
#[structopt(long, use_delimiter = true)]
pub ignore: Vec<String>,

/// Project type configuration
///
/// By default, unused will attempt to detect the type of project you're working on based on
/// heuristics on file or token detection. Setting this will override behavior. If the project
/// type is not found, unused will fallback to default settings (rather than best match).
#[structopt(long)]
pub project_type: Option<String>,

#[structopt(subcommand)]
pub cmd: Option<Command>,
}
Expand Down
2 changes: 1 addition & 1 deletion crates/cli/src/formatters/standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ fn usage_summary(tokens_count: usize, files_count: usize, cli_config: &CliConfig
cli_config.usage_likelihood_filter().join(", ").cyan()
);
println!(
" Configuration setting: {}",
" Project type configuration: {}",
cli_config.configuration_name().cyan()
);
println!("");
Expand Down