Skip to content

Commit

Permalink
refactor: Hoist implementation of tool
Browse files Browse the repository at this point in the history
  • Loading branch information
jpedroh committed Dec 5, 2023
1 parent b2c5e0e commit 9a0afac
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 42 deletions.
73 changes: 73 additions & 0 deletions bin/src/control.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use parsing::ParserConfiguration;

#[derive(Debug)]
pub enum ExecutionError {
ParsingError,
}

#[derive(Debug)]
pub enum ExecutionResult {
WithConflicts(String),
WithoutConflicts(String),
}

impl ToString for ExecutionResult {
fn to_string(&self) -> String {
match self {
ExecutionResult::WithConflicts(value) => value.to_owned(),
ExecutionResult::WithoutConflicts(value) => value.to_owned(),
}
}
}

pub fn run_tool_on_merge_scenario(
language: model::Language,
base: &str,
left: &str,
right: &str,
) -> Result<ExecutionResult, ExecutionError> {
if base == left {
return Ok(ExecutionResult::WithoutConflicts(right.to_string()));
}

if base == right {
return Ok(ExecutionResult::WithoutConflicts(left.to_string()));
}

let parser_configuration = ParserConfiguration::from(language);

let base_tree = parsing::parse_string(&base, &parser_configuration)

Check failure on line 39 in bin/src/control.rs

View workflow job for this annotation

GitHub Actions / clippy

this expression creates a reference which is immediately dereferenced by the compiler
.map_err(|_| ExecutionError::ParsingError)?;
let left_tree = parsing::parse_string(&left, &parser_configuration)

Check failure on line 41 in bin/src/control.rs

View workflow job for this annotation

GitHub Actions / clippy

this expression creates a reference which is immediately dereferenced by the compiler
.map_err(|_| ExecutionError::ParsingError)?;
let right_tree = parsing::parse_string(&right, &parser_configuration)

Check failure on line 43 in bin/src/control.rs

View workflow job for this annotation

GitHub Actions / clippy

this expression creates a reference which is immediately dereferenced by the compiler
.map_err(|_| ExecutionError::ParsingError)?;

let matchings_left_base = matching::calculate_matchings(&left_tree, &base_tree);
let matchings_right_base = matching::calculate_matchings(&right_tree, &base_tree);
let matchings_left_right = matching::calculate_matchings(&left_tree, &right_tree);

let result = merge::merge(
&base_tree,
&left_tree,
&right_tree,
&matchings_left_base,
&matchings_right_base,
&matchings_left_right,
);

match has_conflict(&result) {
true => Ok(ExecutionResult::WithConflicts(result.to_string())),
false => Ok(ExecutionResult::WithoutConflicts(result.to_string())),
}
}

fn has_conflict(result: &merge::MergedCSTNode) -> bool {
match result {
merge::MergedCSTNode::NonTerminal { children, .. } => {
children.into_iter().any(|child| has_conflict(child))

Check failure on line 68 in bin/src/control.rs

View workflow job for this annotation

GitHub Actions / clippy

this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Vec`
}
merge::MergedCSTNode::Terminal { .. } => false,
merge::MergedCSTNode::Conflict { .. } => true,
}
}
11 changes: 4 additions & 7 deletions bin/src/parser_configuration.rs → bin/src/language.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
pub fn get_parser_configuration_by_file_path(
file_path: &std::path::Path,
) -> Result<parsing::ParserConfiguration, String> {
pub fn get_language_by_file_path(file_path: &std::path::Path) -> Result<model::Language, String> {
file_path
.extension()
.and_then(std::ffi::OsStr::to_str)
.and_then(|extension| match extension {
"java" => Some(model::Language::Java),
_ => None,
})
.map(parsing::ParserConfiguration::from)
.ok_or(format!(
"Could not retrieve parsing configuration for file {}",
file_path.display()
Expand All @@ -17,17 +14,17 @@ pub fn get_parser_configuration_by_file_path(

#[cfg(test)]
mod tests {
use crate::parser_configuration::get_parser_configuration_by_file_path;
use crate::language::get_language_by_file_path;

#[test]
fn if_the_file_extension_has_no_parser_available_it_returns_error() {
let file_path = std::path::PathBuf::from("/path/without/extension");
assert!(get_parser_configuration_by_file_path(&file_path).is_err())
assert!(get_language_by_file_path(&file_path).is_err())
}

#[test]
fn if_the_file_extension_has_a_parser_available_it_returns_a_parser_configuration() {
let file_path = std::path::PathBuf::from("/path/for/java/file/Example.java");
assert!(get_parser_configuration_by_file_path(&file_path).is_ok())
assert!(get_language_by_file_path(&file_path).is_ok())
}
}
62 changes: 28 additions & 34 deletions bin/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,40 @@
mod cli_args;
mod parser_configuration;
mod control;
mod language;

use clap::Parser;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = cli_args::CliArgs::parse();

let base = std::fs::read_to_string(&args.base_path)?;
let left = std::fs::read_to_string(args.left_path)?;
let right = std::fs::read_to_string(args.right_path)?;
mod cli_exit_codes {
pub const SUCCESS_WITHOUT_CONFLICTS: i32 = 0;
pub const SUCCESS_WITH_CONFLICTS: i32 = 1;

let parser_configuration =
parser_configuration::get_parser_configuration_by_file_path(&args.base_path)?;

if base == left {
std::fs::write(args.merge_path, right)?;
return Ok(());
}
pub const READING_FILE_ERROR: i32 = 129;
pub const GUESS_LANGUAGE_ERROR: i32 = 130;
pub const WRITING_FILE_ERROR: i32 = 131;
pub const INTERNAL_EXECUTION_ERROR: i32 = 132;
}

if base == right {
std::fs::write(args.merge_path, left)?;
return Ok(());
}
fn main() {
let args = cli_args::CliArgs::parse();

let base_tree = parsing::parse_string(&base, &parser_configuration).unwrap();
let left_tree = parsing::parse_string(&left, &parser_configuration).unwrap();
let right_tree = parsing::parse_string(&right, &parser_configuration).unwrap();
let base = std::fs::read_to_string(&args.base_path)
.unwrap_or_else(|_| std::process::exit(cli_exit_codes::READING_FILE_ERROR));
let left = std::fs::read_to_string(args.left_path)
.unwrap_or_else(|_| std::process::exit(cli_exit_codes::READING_FILE_ERROR));
let right = std::fs::read_to_string(args.right_path)
.unwrap_or_else(|_| std::process::exit(cli_exit_codes::READING_FILE_ERROR));

let matchings_left_base = matching::calculate_matchings(&left_tree, &base_tree);
let matchings_right_base = matching::calculate_matchings(&right_tree, &base_tree);
let matchings_left_right = matching::calculate_matchings(&left_tree, &right_tree);
let language = language::get_language_by_file_path(&args.base_path)
.unwrap_or_else(|_| std::process::exit(cli_exit_codes::GUESS_LANGUAGE_ERROR));

let result = merge::merge(
&base_tree,
&left_tree,
&right_tree,
&matchings_left_base,
&matchings_right_base,
&matchings_left_right,
);
let result = control::run_tool_on_merge_scenario(language, &base, &left, &right)
.unwrap_or_else(|_| std::process::exit(cli_exit_codes::INTERNAL_EXECUTION_ERROR));

std::fs::write(args.merge_path, result.to_string())?;
std::fs::write(args.merge_path, result.to_string())
.unwrap_or_else(|_| std::process::exit(cli_exit_codes::WRITING_FILE_ERROR));

Ok(())
match result {
control::ExecutionResult::WithConflicts(_) => std::process::exit(cli_exit_codes::SUCCESS_WITH_CONFLICTS),
control::ExecutionResult::WithoutConflicts(_) => std::process::exit(cli_exit_codes::SUCCESS_WITHOUT_CONFLICTS),
}
}
2 changes: 1 addition & 1 deletion merge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ mod merged_cst_node;
mod ordered_merge;
mod unordered_merge;

use merged_cst_node::MergedCSTNode;
use ordered_merge::ordered_merge;
use unordered_merge::unordered_merge;

pub use merge::merge;
pub use merged_cst_node::MergedCSTNode;

0 comments on commit 9a0afac

Please sign in to comment.