Skip to content

Commit d34ace5

Browse files
committed
cli: Update cli
1 parent 2e4ed61 commit d34ace5

File tree

1 file changed

+35
-139
lines changed

1 file changed

+35
-139
lines changed

rust-code-analysis-cli/src/main.rs

Lines changed: 35 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,13 @@ extern crate toml;
1111
mod formats;
1212

1313
use clap::{App, Arg};
14-
use crossbeam::channel::{unbounded, Receiver, Sender};
1514
use globset::{Glob, GlobSet, GlobSetBuilder};
1615
use std::collections::{hash_map, HashMap};
1716
use std::fmt;
18-
use std::path::PathBuf;
17+
use std::path::{Path, PathBuf};
18+
use std::process;
1919
use std::str::FromStr;
2020
use std::sync::{Arc, Mutex};
21-
use std::{process, thread};
22-
use walkdir::{DirEntry, WalkDir};
2321

2422
use formats::Format;
2523

@@ -28,8 +26,9 @@ use rust_code_analysis::LANG;
2826

2927
// Structs
3028
use rust_code_analysis::{
31-
CommentRm, CommentRmCfg, Count, CountCfg, Dump, DumpCfg, Find, FindCfg, Function, FunctionCfg,
32-
Metrics, MetricsCfg, OpsCfg, OpsCode, PreprocParser, PreprocResults,
29+
CommentRm, CommentRmCfg, ConcurrentRunner, Count, CountCfg, Dump, DumpCfg, FilesData, Find,
30+
FindCfg, Function, FunctionCfg, Metrics, MetricsCfg, OpsCfg, OpsCode, PreprocParser,
31+
PreprocResults,
3332
};
3433

3534
// Functions
@@ -48,6 +47,7 @@ struct Config {
4847
comments: bool,
4948
find_filter: Vec<String>,
5049
count_filter: Vec<String>,
50+
language: Option<LANG>,
5151
function: bool,
5252
metrics: bool,
5353
ops: bool,
@@ -61,15 +61,6 @@ struct Config {
6161
count_lock: Option<Arc<Mutex<Count>>>,
6262
}
6363

64-
struct JobItem {
65-
language: Option<LANG>,
66-
path: PathBuf,
67-
cfg: Arc<Config>,
68-
}
69-
70-
type JobReceiver = Receiver<Option<JobItem>>;
71-
type JobSender = Sender<Option<JobItem>>;
72-
7364
fn mk_globset(elems: clap::Values) -> GlobSet {
7465
let mut globset = GlobSetBuilder::new();
7566
for e in elems {
@@ -86,14 +77,14 @@ fn mk_globset(elems: clap::Values) -> GlobSet {
8677
}
8778
}
8879

89-
fn act_on_file(language: Option<LANG>, path: PathBuf, cfg: &Config) -> std::io::Result<()> {
80+
fn act_on_file(path: PathBuf, cfg: &Config) -> std::io::Result<()> {
9081
let source = if let Some(source) = read_file_with_eol(&path)? {
9182
source
9283
} else {
9384
return Ok(());
9485
};
9586

96-
let language = if let Some(language) = language {
87+
let language = if let Some(language) = cfg.language {
9788
language
9889
} else if let Some(language) = guess_language(&source, &path).0 {
9990
language
@@ -174,90 +165,18 @@ fn act_on_file(language: Option<LANG>, path: PathBuf, cfg: &Config) -> std::io::
174165
}
175166
}
176167

177-
fn consumer(receiver: JobReceiver) {
178-
while let Ok(job) = receiver.recv() {
179-
if job.is_none() {
180-
break;
181-
}
182-
let job = job.unwrap();
183-
let path = job.path.clone();
184-
185-
if let Err(err) = act_on_file(job.language, job.path, &job.cfg) {
186-
eprintln!("{:?} for file {:?}", err, path);
187-
}
188-
}
189-
}
190-
191-
fn send_file(path: PathBuf, cfg: &Arc<Config>, language: Option<LANG>, sender: &JobSender) {
192-
sender
193-
.send(Some(JobItem {
194-
language,
195-
path,
196-
cfg: Arc::clone(cfg),
197-
}))
198-
.unwrap();
199-
}
200-
201-
fn is_hidden(entry: &DirEntry) -> bool {
202-
entry
203-
.file_name()
204-
.to_str()
205-
.map(|s| s.starts_with('.'))
206-
.unwrap_or(false)
207-
}
208-
209-
fn explore(
210-
mut paths: Vec<String>,
211-
cfg: &Arc<Config>,
212-
include: GlobSet,
213-
exclude: GlobSet,
214-
language: Option<LANG>,
215-
sender: &JobSender,
216-
) -> HashMap<String, Vec<PathBuf>> {
217-
let mut all_files: HashMap<String, Vec<PathBuf>> = HashMap::new();
218-
219-
for path in paths.drain(..) {
220-
let path = PathBuf::from(path);
221-
if !path.exists() {
222-
eprintln!("Warning: File doesn't exist: {}", path.to_str().unwrap());
223-
continue;
224-
}
225-
if path.is_dir() {
226-
for entry in WalkDir::new(path)
227-
.into_iter()
228-
.filter_entry(|e| !is_hidden(e))
229-
{
230-
let entry = entry.unwrap();
231-
let path = entry.path().to_path_buf();
232-
if (include.is_empty() || include.is_match(&path))
233-
&& (exclude.is_empty() || !exclude.is_match(&path))
234-
&& path.is_file()
235-
{
236-
if cfg.preproc_lock.is_some() {
237-
let file_name = path.file_name().unwrap().to_str().unwrap().to_string();
238-
let path = path.clone();
239-
match all_files.entry(file_name) {
240-
hash_map::Entry::Occupied(l) => {
241-
l.into_mut().push(path);
242-
}
243-
hash_map::Entry::Vacant(p) => {
244-
p.insert(vec![path]);
245-
}
246-
};
247-
}
248-
249-
send_file(path, cfg, language, sender);
250-
}
168+
fn process_dir_path(all_files: &mut HashMap<String, Vec<PathBuf>>, path: &Path, cfg: &Config) {
169+
if cfg.preproc_lock.is_some() {
170+
let file_name = path.file_name().unwrap().to_str().unwrap().to_string();
171+
match all_files.entry(file_name) {
172+
hash_map::Entry::Occupied(l) => {
173+
l.into_mut().push(path.to_path_buf());
251174
}
252-
} else if (include.is_empty() || include.is_match(&path))
253-
&& (exclude.is_empty() || !exclude.is_match(&path))
254-
&& path.is_file()
255-
{
256-
send_file(path, cfg, language, sender);
257-
}
175+
hash_map::Entry::Vacant(p) => {
176+
p.insert(vec![path.to_path_buf()]);
177+
}
178+
};
258179
}
259-
260-
all_files
261180
}
262181

263182
fn parse_or_exit<T>(s: &str) -> T
@@ -503,12 +422,16 @@ fn main() {
503422
None
504423
};
505424

506-
let cfg = Arc::new(Config {
425+
let include = mk_globset(matches.values_of("include").unwrap());
426+
let exclude = mk_globset(matches.values_of("exclude").unwrap());
427+
428+
let cfg = Config {
507429
dump,
508430
in_place,
509431
comments,
510432
find_filter,
511433
count_filter,
434+
language,
512435
function,
513436
metrics,
514437
ops,
@@ -520,51 +443,24 @@ fn main() {
520443
preproc_lock: preproc_lock.clone(),
521444
preproc,
522445
count_lock: count_lock.clone(),
523-
});
524-
525-
let (sender, receiver) = unbounded();
526-
527-
let producer = {
528-
let sender = sender.clone();
529-
let include = mk_globset(matches.values_of("include").unwrap());
530-
let exclude = mk_globset(matches.values_of("exclude").unwrap());
531-
532-
thread::Builder::new()
533-
.name(String::from("Producer"))
534-
.spawn(move || explore(paths, &cfg, include, exclude, language, &sender))
535-
.unwrap()
536446
};
537447

538-
let mut receivers = Vec::with_capacity(num_jobs);
539-
for i in 0..num_jobs {
540-
let receiver = receiver.clone();
541-
542-
let t = thread::Builder::new()
543-
.name(format!("Consumer {}", i))
544-
.spawn(move || {
545-
consumer(receiver);
546-
})
547-
.unwrap();
548-
549-
receivers.push(t);
550-
}
551-
552-
let all_files = if let Ok(res) = producer.join() {
553-
res
554-
} else {
555-
process::exit(1);
448+
let files_data = FilesData {
449+
include,
450+
exclude,
451+
paths,
556452
};
557453

558-
// Poison the receiver, now that the producer is finished.
559-
for _ in 0..num_jobs {
560-
sender.send(None).unwrap();
561-
}
562-
563-
for receiver in receivers {
564-
if receiver.join().is_err() {
454+
let all_files = match ConcurrentRunner::new(num_jobs, act_on_file)
455+
.set_proc_dir_paths(process_dir_path)
456+
.run(cfg, files_data)
457+
{
458+
Ok(all_files) => all_files,
459+
Err(e) => {
460+
eprintln!("{:?}", e);
565461
process::exit(1);
566462
}
567-
}
463+
};
568464

569465
if let Some(count) = count_lock {
570466
let count = Arc::try_unwrap(count).unwrap().into_inner().unwrap();

0 commit comments

Comments
 (0)