Skip to content

Commit

Permalink
Move the dump formats code from lib to cli
Browse files Browse the repository at this point in the history
  • Loading branch information
Luni-4 committed Aug 5, 2020
1 parent 580a8bc commit c17e003
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 200 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,8 @@ petgraph = "^0.5"
phf = { version = "^0.8", features = ["macros"] }
regex = "^1.1"
serde = { version = "^1.0", features = ["derive"] }
serde_cbor = "^0.11"
serde_json = "^1.0"
termcolor = "^1.0"
tree-sitter = "^0.16"
serde_yaml = "^0.8"
toml = "^0.5"

[dev-dependencies]
pretty_assertions = "^0.6"
Expand Down
4 changes: 4 additions & 0 deletions rust-code-analysis-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@ crossbeam = "^0.7"
futures = "^0.3"
globset = "^0.4"
num_cpus = "^1.13"
regex = "^1.1"
rust-code-analysis = { path = "..", version = "0.0"}
serde = "^1.0"
serde_cbor = "^0.11"
serde_json = "^1.0"
serde_yaml = "^0.8"
toml = "^0.5"
walkdir = "^2.2"

[dev-dependencies]
Expand Down
122 changes: 122 additions & 0 deletions rust-code-analysis-cli/src/formats.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
use regex::Regex;
use std::fs::File;
use std::io::Write;
use std::io::{Error, ErrorKind};
use std::path::PathBuf;
use std::str::FromStr;

use rust_code_analysis::FuncSpace;

#[derive(Debug, Clone)]
pub enum Format {
Cbor,
Json,
Toml,
Yaml,
}

impl Format {
pub fn all() -> &'static [&'static str] {
&["cbor", "json", "toml", "yaml"]
}

pub fn dump_formats(
&self,
space: &FuncSpace,
path: &PathBuf,
output_path: &Option<PathBuf>,
pretty: bool,
) -> std::io::Result<()> {
if output_path.is_none() {
let stdout = std::io::stdout();
let mut stdout = stdout.lock();

match self {
Format::Cbor => Err(Error::new(
ErrorKind::Other,
"Cbor format cannot be printed to stdout",
)),
Format::Json => {
let json_data = if pretty {
serde_json::to_string_pretty(&space).unwrap()
} else {
serde_json::to_string(&space).unwrap()
};
write!(stdout, "{}", json_data)
}
Format::Toml => {
let toml_data = if pretty {
toml::to_string_pretty(&space).unwrap()
} else {
toml::to_string(&space).unwrap()
};
write!(stdout, "{}", toml_data)
}
Format::Yaml => write!(stdout, "{}", serde_yaml::to_string(&space).unwrap()),
}
} else {
let format_ext = match self {
Format::Cbor => ".cbor",
Format::Json => ".json",
Format::Toml => ".toml",
Format::Yaml => ".yml",
};

let output_path = output_path.as_ref().unwrap();

let mut file = path.as_path().file_name().unwrap().to_os_string();
file.push(format_ext);

let mut format_path = output_path.clone();
format_path.push(file);

if format_path.as_path().exists() {
let mut new_filename = path.to_str().unwrap().to_string();
let re = Regex::new(r"[\\:/]").unwrap();
new_filename = re.replace_all(&new_filename, "_").to_string();
new_filename.push_str(format_ext);
format_path.pop();
format_path.push(new_filename);
}

let mut format_file = File::create(format_path)?;
match self {
Format::Cbor => serde_cbor::to_writer(format_file, &space)
.map_err(|e| Error::new(ErrorKind::Other, e.to_string())),
Format::Json => {
if pretty {
serde_json::to_writer_pretty(format_file, &space)
.map_err(|e| Error::new(ErrorKind::Other, e.to_string()))
} else {
serde_json::to_writer(format_file, &space)
.map_err(|e| Error::new(ErrorKind::Other, e.to_string()))
}
}
Format::Toml => {
let toml_data = if pretty {
toml::to_string_pretty(&space).unwrap()
} else {
toml::to_string(&space).unwrap()
};
format_file.write_all(toml_data.as_bytes())
}
Format::Yaml => serde_yaml::to_writer(format_file, &space)
.map_err(|e| Error::new(ErrorKind::Other, e.to_string())),
}
}
}
}

impl FromStr for Format {
type Err = String;

fn from_str(format: &str) -> Result<Self, Self::Err> {
match format {
"cbor" => Ok(Format::Cbor),
"json" => Ok(Format::Json),
"toml" => Ok(Format::Toml),
"yaml" => Ok(Format::Yaml),
format => Err(format!("{:?} is not a supported format", format)),
}
}
}
38 changes: 19 additions & 19 deletions rust-code-analysis-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ extern crate crossbeam;
extern crate num_cpus;
#[macro_use]
extern crate serde;
extern crate serde_cbor;
#[cfg_attr(test, macro_use)]
extern crate serde_json;
extern crate serde_yaml;
extern crate toml;

mod formats;
mod web;

use clap::{App, Arg};
Expand All @@ -21,6 +25,7 @@ use std::sync::{Arc, Mutex};
use std::{process, thread};
use walkdir::{DirEntry, WalkDir};

use formats::Format;
use rust_code_analysis::*;
use web::server;

Expand All @@ -34,7 +39,7 @@ struct Config {
function: bool,
metrics: bool,
output_format: Option<Format>,
output: String,
output: Option<PathBuf>,
pretty: bool,
line_start: Option<usize>,
line_end: Option<usize>,
Expand Down Expand Up @@ -91,17 +96,13 @@ fn act_on_file(language: Option<LANG>, path: PathBuf, cfg: &Config) -> std::io::
};
action::<Dump>(&language, source, &path, pr, cfg)
} else if cfg.metrics {
let cfg = MetricsCfg {
path,
output_format: cfg.output_format.clone(),
pretty: cfg.pretty,
output_path: if cfg.output.is_empty() {
None
} else {
Some(PathBuf::from(cfg.output.clone()))
},
};
action::<Metrics>(&language, source, &cfg.path.clone(), pr, cfg)
if let Some(output_format) = &cfg.output_format {
let space = get_function_spaces(&language, source, &path, pr).unwrap();
output_format.dump_formats(&space, &path, &cfg.output, cfg.pretty)
} else {
let cfg = MetricsCfg { path };
action::<Metrics>(&language, source, &cfg.path.clone(), pr, cfg)
}
} else if cfg.comments {
let cfg = CommentRmCfg {
in_place: cfg.in_place,
Expand Down Expand Up @@ -474,9 +475,9 @@ fn main() {
.value_of("output_format")
.map(parse_or_exit::<Format>);
let pretty = matches.is_present("pretty");
let output = matches.value_of("output").unwrap().to_string();
let output_is_dir = PathBuf::from(output.clone()).is_dir();
if metrics && !output.is_empty() && !output_is_dir {
let output = matches.value_of("output").map(|s| PathBuf::from(s));
let output_is_dir = output.as_ref().map(|p| p.is_dir()).unwrap_or(false);
if metrics && output.is_some() && !output_is_dir {
eprintln!("Error: The output parameter must be a directory");
process::exit(1);
}
Expand Down Expand Up @@ -576,11 +577,10 @@ fn main() {
fix_includes(&mut data.files, &all_files);

let data = serde_json::to_string(&data).unwrap();
if output.is_empty() {
println!("{}", data);
if let Some(output_path) = output {
write_file(&output_path, data.as_bytes()).unwrap();
} else {
let output = PathBuf::from(output);
write_file(&output, data.as_bytes()).unwrap();
println!("{}", data);
}
}
}
Expand Down
4 changes: 0 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@
extern crate lazy_static;
#[macro_use]
extern crate serde;
extern crate serde_cbor;
extern crate serde_json;
extern crate serde_yaml;
extern crate toml;

#[macro_use]
mod asttools;
Expand Down
35 changes: 32 additions & 3 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,6 @@ macro_rules! mk_action {
/// // Configuration options used by the function which computes the metrics
/// let cfg = MetricsCfg {
/// path,
/// output_format: None,
/// pretty: false,
/// output_path: None,
/// };
///
/// action::<Metrics>(&language, source_as_vec, &cfg.path.clone(), None, cfg);
Expand All @@ -127,6 +124,38 @@ macro_rules! mk_action {
)*
}
}

/// Returns all function spaces data of a code.
///
/// # Examples
///
/// ```
/// use std::path::PathBuf;
///
/// use rust_code_analysis::{get_function_spaces, LANG};
///
/// # fn main() {
/// let source_code = "int a = 42;";
/// let language = LANG::Cpp;
///
/// // The path to a dummy file used to contain the source code
/// let path = PathBuf::from("foo.c");
/// let source_as_vec = source_code.as_bytes().to_vec();
///
/// get_function_spaces(&language, source_as_vec, &path, None).unwrap();
/// # }
/// ```
#[inline(always)]
pub fn get_function_spaces(lang: &LANG, source: Vec<u8>, path: &PathBuf, pr: Option<Arc<PreprocResults>>) -> Option<FuncSpace> {
match lang {
$(
LANG::$camel => {
let parser = $parser::new(source, &path, pr);
metrics(&parser, &path)
},
)*
}
}
};
}

Expand Down
Loading

0 comments on commit c17e003

Please sign in to comment.