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

feat: shorten output for grammar fetching and building #3396

Merged
merged 1 commit into from
Aug 17, 2022
Merged
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
157 changes: 129 additions & 28 deletions helix-loader/src/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,102 @@ pub fn fetch_grammars() -> Result<()> {
let mut grammars = get_grammar_configs()?;
grammars.retain(|grammar| !matches!(grammar.source, GrammarSource::Local { .. }));

run_parallel(grammars, fetch_grammar, "fetch")
println!("Fetching {} grammars", grammars.len());
let results = run_parallel(grammars, fetch_grammar);

let mut errors = Vec::new();
let mut git_updated = Vec::new();
let mut git_up_to_date = 0;
let mut non_git = Vec::new();

for res in results {
match res {
Ok(FetchStatus::GitUpToDate) => git_up_to_date += 1,
Ok(FetchStatus::GitUpdated {
grammar_id,
revision,
}) => git_updated.push((grammar_id, revision)),
Ok(FetchStatus::NonGit { grammar_id }) => non_git.push(grammar_id),
Err(e) => errors.push(e),
}
}

non_git.sort_unstable();
git_updated.sort_unstable_by(|a, b| a.0.cmp(&b.0));

if git_up_to_date != 0 {
println!("{} up to date git grammars", git_up_to_date);
}

if !non_git.is_empty() {
println!("{} non git grammars", non_git.len());
println!("\t{:?}", non_git);
}

if !git_updated.is_empty() {
println!("{} updated grammars", git_updated.len());
// We checked the vec is not empty, unwrapping will not panic
let longest_id = git_updated.iter().map(|x| x.0.len()).max().unwrap();
for (id, rev) in git_updated {
println!(
"\t{id:width$} now on {rev}",
id = id,
width = longest_id,
rev = rev
);
}
}

if !errors.is_empty() {
let len = errors.len();
println!("{} grammars failed to fetch", len);
for (i, error) in errors.into_iter().enumerate() {
println!("\tFailure {}/{}: {}", i, len, error);
}
}

Ok(())
}

pub fn build_grammars(target: Option<String>) -> Result<()> {
run_parallel(
get_grammar_configs()?,
move |grammar| build_grammar(grammar, target.as_deref()),
"build",
)
let grammars = get_grammar_configs()?;
println!("Building {} grammars", grammars.len());
let results = run_parallel(grammars, move |grammar| {
build_grammar(grammar, target.as_deref())
});

let mut errors = Vec::new();
let mut already_built = 0;
let mut built = Vec::new();

for res in results {
match res {
Ok(BuildStatus::AlreadyBuilt) => already_built += 1,
Ok(BuildStatus::Built { grammar_id }) => built.push(grammar_id),
Err(e) => errors.push(e),
}
}

built.sort_unstable();

if already_built != 0 {
println!("{} grammars already built", already_built);
}

if !built.is_empty() {
println!("{} grammars built now", built.len());
println!("\t{:?}", built);
}

if !errors.is_empty() {
let len = errors.len();
println!("{} grammars failed to build", len);
for (i, error) in errors.into_iter().enumerate() {
println!("\tFailure {}/{}: {}", i, len, error);
}
}

Ok(())
}

// Returns the set of grammar configurations the user requests.
Expand Down Expand Up @@ -126,9 +213,10 @@ fn get_grammar_configs() -> Result<Vec<GrammarConfiguration>> {
Ok(grammars)
}

fn run_parallel<F>(grammars: Vec<GrammarConfiguration>, job: F, action: &'static str) -> Result<()>
fn run_parallel<F, Res>(grammars: Vec<GrammarConfiguration>, job: F) -> Vec<Result<Res>>
where
F: Fn(GrammarConfiguration) -> Result<()> + std::marker::Send + 'static + Clone,
F: Fn(GrammarConfiguration) -> Result<Res> + Send + 'static + Clone,
Res: Send + 'static,
{
let pool = threadpool::Builder::new().build();
let (tx, rx) = channel();
Expand All @@ -146,14 +234,21 @@ where

drop(tx);

// TODO: print all failures instead of the first one found.
rx.iter()
.find(|result| result.is_err())
.map(|err| err.with_context(|| format!("Failed to {} some grammar(s)", action)))
.unwrap_or(Ok(()))
rx.iter().collect()
}

enum FetchStatus {
GitUpToDate,
GitUpdated {
grammar_id: String,
revision: String,
},
NonGit {
grammar_id: String,
},
}

fn fetch_grammar(grammar: GrammarConfiguration) -> Result<()> {
fn fetch_grammar(grammar: GrammarConfiguration) -> Result<FetchStatus> {
if let GrammarSource::Git {
remote, revision, ..
} = grammar.source
Expand Down Expand Up @@ -189,16 +284,18 @@ fn fetch_grammar(grammar: GrammarConfiguration) -> Result<()> {
)?;
git(&grammar_dir, ["checkout", &revision])?;

println!(
"Grammar '{}' checked out at '{}'.",
grammar.grammar_id, revision
);
Ok(FetchStatus::GitUpdated {
grammar_id: grammar.grammar_id,
revision,
})
} else {
println!("Grammar '{}' is already up to date.", grammar.grammar_id);
Ok(FetchStatus::GitUpToDate)
}
} else {
Ok(FetchStatus::NonGit {
grammar_id: grammar.grammar_id,
})
}

Ok(())
}

// Sets the remote for a repository to the given URL, creating the remote if
Expand Down Expand Up @@ -245,7 +342,12 @@ where
}
}

fn build_grammar(grammar: GrammarConfiguration, target: Option<&str>) -> Result<()> {
enum BuildStatus {
AlreadyBuilt,
Built { grammar_id: String },
}

fn build_grammar(grammar: GrammarConfiguration, target: Option<&str>) -> Result<BuildStatus> {
let grammar_dir = if let GrammarSource::Local { path } = &grammar.source {
PathBuf::from(&path)
} else {
Expand Down Expand Up @@ -285,7 +387,7 @@ fn build_tree_sitter_library(
src_path: &Path,
grammar: GrammarConfiguration,
target: Option<&str>,
) -> Result<()> {
) -> Result<BuildStatus> {
let header_path = src_path;
let parser_path = src_path.join("parser.c");
let mut scanner_path = src_path.join("scanner.c");
Expand All @@ -308,12 +410,9 @@ fn build_tree_sitter_library(
.context("Failed to compare source and binary timestamps")?;

if !recompile {
println!("Grammar '{}' is already built.", grammar.grammar_id);
return Ok(());
return Ok(BuildStatus::AlreadyBuilt);
}

println!("Building grammar '{}'", grammar.grammar_id);

let mut config = cc::Build::new();
config
.cpp(true)
Expand Down Expand Up @@ -381,7 +480,9 @@ fn build_tree_sitter_library(
));
}

Ok(())
Ok(BuildStatus::Built {
grammar_id: grammar.grammar_id,
})
}

fn needs_recompile(
Expand Down