diff --git a/cli/loader/Cargo.toml b/cli/loader/Cargo.toml index bff2f630..5179b36d 100644 --- a/cli/loader/Cargo.toml +++ b/cli/loader/Cargo.toml @@ -14,6 +14,9 @@ categories.workspace = true [features] wasm = ["tree-sitter/wasm"] +# TODO: For backward compatibility these must be enabled by default, +# consider removing for the next semver incompatible release +default = ["tree-sitter-highlight", "tree-sitter-tags"] [dependencies] anyhow.workspace = true @@ -28,6 +31,6 @@ serde.workspace = true serde_json.workspace = true tempfile.workspace = true -tree-sitter.workspace = true -tree-sitter-highlight.workspace = true -tree-sitter-tags.workspace = true +tree-sitter = {workspace = true} +tree-sitter-highlight = {workspace = true, optional = true} +tree-sitter-tags = {workspace = true, optional = true} diff --git a/cli/loader/src/lib.rs b/cli/loader/src/lib.rs index eb829373..56ab0e65 100644 --- a/cli/loader/src/lib.rs +++ b/cli/loader/src/lib.rs @@ -1,5 +1,9 @@ #![doc = include_str!("../README.md")] +#[cfg(any(feature = "tree-sitter-highlight", feature = "tree-sitter-tags"))] +use std::ops::Range; +#[cfg(feature = "tree-sitter-highlight")] +use std::sync::Mutex; use std::{ collections::HashMap, env, @@ -7,22 +11,28 @@ use std::{ fs, io::{BufRead, BufReader}, mem, - ops::Range, path::{Path, PathBuf}, process::Command, - sync::Mutex, time::SystemTime, }; -use anyhow::{anyhow, Context, Error, Result}; +#[cfg(any(feature = "tree-sitter-highlight", feature = "tree-sitter-tags"))] +use anyhow::Error; +use anyhow::{anyhow, Context, Result}; use fs4::FileExt; use indoc::indoc; use libloading::{Library, Symbol}; use once_cell::unsync::OnceCell; use regex::{Regex, RegexBuilder}; use serde::{Deserialize, Deserializer, Serialize}; -use tree_sitter::{Language, QueryError, QueryErrorKind}; +use tree_sitter::Language; +#[cfg(any(feature = "tree-sitter-highlight", feature = "tree-sitter-tags"))] +use tree_sitter::QueryError; +#[cfg(feature = "tree-sitter-highlight")] +use tree_sitter::QueryErrorKind; +#[cfg(feature = "tree-sitter-highlight")] use tree_sitter_highlight::HighlightConfiguration; +#[cfg(feature = "tree-sitter-tags")] use tree_sitter_tags::{Error as TagsError, TagsConfiguration}; pub const EMSCRIPTEN_TAG: &str = concat!("docker.io/emscripten/emsdk:", env!("EMSCRIPTEN_VERSION")); @@ -98,9 +108,13 @@ pub struct LanguageConfiguration<'a> { pub tags_filenames: Option>, pub language_name: String, language_id: usize, + #[cfg(feature = "tree-sitter-highlight")] highlight_config: OnceCell>, + #[cfg(feature = "tree-sitter-tags")] tags_config: OnceCell>, + #[cfg(feature = "tree-sitter-highlight")] highlight_names: &'a Mutex>, + #[cfg(feature = "tree-sitter-highlight")] use_all_highlight_names: bool, } @@ -111,7 +125,9 @@ pub struct Loader { language_configuration_ids_by_file_type: HashMap>, language_configuration_in_current_path: Option, language_configuration_ids_by_first_line_regex: HashMap>, + #[cfg(feature = "tree-sitter-highlight")] highlight_names: Box>>, + #[cfg(feature = "tree-sitter-highlight")] use_all_highlight_names: bool, debug_build: bool, sanitize_build: bool, @@ -177,7 +193,9 @@ impl Loader { language_configuration_ids_by_file_type: HashMap::new(), language_configuration_in_current_path: None, language_configuration_ids_by_first_line_regex: HashMap::new(), + #[cfg(feature = "tree-sitter-highlight")] highlight_names: Box::new(Mutex::new(Vec::new())), + #[cfg(feature = "tree-sitter-highlight")] use_all_highlight_names: true, debug_build: false, sanitize_build: false, @@ -187,6 +205,7 @@ impl Loader { } } + #[cfg(feature = "tree-sitter-highlight")] pub fn configure_highlights(&mut self, names: &[String]) { self.use_all_highlight_names = false; let mut highlights = self.highlight_names.lock().unwrap(); @@ -195,6 +214,7 @@ impl Loader { } #[must_use] + #[cfg(feature = "tree-sitter-highlight")] pub fn highlight_names(&self) -> Vec { self.highlight_names.lock().unwrap().clone() } @@ -889,6 +909,7 @@ impl Loader { } #[must_use] + #[cfg(feature = "tree-sitter-highlight")] pub fn highlight_config_for_injection_string<'a>( &'a self, string: &str, @@ -1041,9 +1062,13 @@ impl Loader { locals_filenames: config_json.locals.into_vec(), tags_filenames: config_json.tags.into_vec(), highlights_filenames: config_json.highlights.into_vec(), + #[cfg(feature = "tree-sitter-highlight")] highlight_config: OnceCell::new(), + #[cfg(feature = "tree-sitter-tags")] tags_config: OnceCell::new(), + #[cfg(feature = "tree-sitter-highlight")] highlight_names: &self.highlight_names, + #[cfg(feature = "tree-sitter-highlight")] use_all_highlight_names: self.use_all_highlight_names, }; @@ -1098,9 +1123,13 @@ impl Loader { locals_filenames: None, highlights_filenames: None, tags_filenames: None, + #[cfg(feature = "tree-sitter-highlight")] highlight_config: OnceCell::new(), + #[cfg(feature = "tree-sitter-tags")] tags_config: OnceCell::new(), + #[cfg(feature = "tree-sitter-highlight")] highlight_names: &self.highlight_names, + #[cfg(feature = "tree-sitter-highlight")] use_all_highlight_names: self.use_all_highlight_names, }; self.language_configurations.push(unsafe { @@ -1187,6 +1216,7 @@ impl Loader { } impl<'a> LanguageConfiguration<'a> { + #[cfg(feature = "tree-sitter-highlight")] pub fn highlight_config( &self, language: Language, @@ -1197,14 +1227,14 @@ impl<'a> LanguageConfiguration<'a> { Some( paths .iter() - .filter(|p| p.ends_with("highlights.scm")) + .filter(|p| p.ends_with("tree-sitter-highlights.scm")) .cloned() .collect::>(), ), Some( paths .iter() - .filter(|p| p.ends_with("tags.scm")) + .filter(|p| p.ends_with("tree-sitter-tags.scm")) .cloned() .collect::>(), ), @@ -1226,7 +1256,7 @@ impl<'a> LanguageConfiguration<'a> { } else { self.highlights_filenames.as_deref() }, - "highlights.scm", + "tree-sitter-highlights.scm", )?; let (injections_query, injection_ranges) = self.read_queries( if injections_filenames.is_some() { @@ -1298,11 +1328,12 @@ impl<'a> LanguageConfiguration<'a> { .map(Option::as_ref) } + #[cfg(feature = "tree-sitter-tags")] pub fn tags_config(&self, language: Language) -> Result> { self.tags_config .get_or_try_init(|| { let (tags_query, tags_ranges) = - self.read_queries(self.tags_filenames.as_deref(), "tags.scm")?; + self.read_queries(self.tags_filenames.as_deref(), "tree-sitter-tags.scm")?; let (locals_query, locals_ranges) = self.read_queries(self.locals_filenames.as_deref(), "locals.scm")?; if tags_query.is_empty() { @@ -1336,6 +1367,7 @@ impl<'a> LanguageConfiguration<'a> { .map(Option::as_ref) } + #[cfg(any(feature = "tree-sitter-highlight", feature = "tree-sitter-tags"))] fn include_path_in_query_error( mut error: QueryError, ranges: &[(String, Range)], @@ -1349,12 +1381,13 @@ impl<'a> LanguageConfiguration<'a> { .unwrap_or_else(|| ranges.last().unwrap()); error.offset = offset_within_section - range.start; error.row = source[range.start..offset_within_section] - .matches(|c| c == '\n') + .matches('\n') .count(); Error::from(error).context(format!("Error in query file {path:?}")) } #[allow(clippy::type_complexity)] + #[cfg(any(feature = "tree-sitter-highlight", feature = "tree-sitter-tags"))] fn read_queries( &self, paths: Option<&[String]>, @@ -1372,7 +1405,9 @@ impl<'a> LanguageConfiguration<'a> { } } else { // highlights.scm is needed to test highlights, and tags.scm to test tags - if default_path == "highlights.scm" || default_path == "tags.scm" { + if default_path == "tree-sitter-highlights.scm" + || default_path == "tree-sitter-tags.scm" + { eprintln!( indoc! {" Warning: you should add a `{}` entry pointing to the highlights path in `tree-sitter` language list in the grammar's package.json