aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--helix-loader/src/grammar.rs157
1 files changed, 129 insertions, 28 deletions
diff --git a/helix-loader/src/grammar.rs b/helix-loader/src/grammar.rs
index 231ecf34..98a93e56 100644
--- a/helix-loader/src/grammar.rs
+++ b/helix-loader/src/grammar.rs
@@ -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.
@@ -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();
@@ -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
@@ -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
@@ -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 {
@@ -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");
@@ -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)
@@ -381,7 +480,9 @@ fn build_tree_sitter_library(
));
}
- Ok(())
+ Ok(BuildStatus::Built {
+ grammar_id: grammar.grammar_id,
+ })
}
fn needs_recompile(