Skip to content

Commit 21668c7

Browse files
committed
Add the syn_loader to Document
This type also exists on `Editor`. This change brings it to the `Document` as well because the replacement for `Syntax` in the child commits will eliminate `Syntax`'s copy of `syn_loader`. `Syntax` will also be responsible for returning the highlighter and query iterators (which will borrow the loader), so the loader must be separated from that type. In the long run, when we make a larger refactor to have `Document::apply` be a function of the `Editor` instead of the `Document`, we will be able to drop this field on `Document` - it is currently only necessary for `Document::apply`. Once we make that refactor, we will be able to eliminate the surrounding `Arc` in `Arc<ArcSwap<syntax::Loader>>` and use the `ArcSwap` directly instead.
1 parent 9c4d567 commit 21668c7

File tree

8 files changed

+94
-44
lines changed

8 files changed

+94
-44
lines changed

helix-core/src/syntax.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,15 @@ struct FileTypeGlobMatcher {
274274
file_types: Vec<FileTypeGlob>,
275275
}
276276

277+
impl Default for FileTypeGlobMatcher {
278+
fn default() -> Self {
279+
Self {
280+
matcher: globset::GlobSet::empty(),
281+
file_types: Default::default(),
282+
}
283+
}
284+
}
285+
277286
impl FileTypeGlobMatcher {
278287
fn new(file_types: Vec<FileTypeGlob>) -> Result<Self, globset::Error> {
279288
let mut builder = globset::GlobSetBuilder::new();
@@ -299,7 +308,7 @@ impl FileTypeGlobMatcher {
299308

300309
// Expose loader as Lazy<> global since it's always static?
301310

302-
#[derive(Debug)]
311+
#[derive(Debug, Default)]
303312
pub struct Loader {
304313
// highlight_names ?
305314
language_configs: Vec<Arc<LanguageConfiguration>>,

helix-term/src/application.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,8 +389,9 @@ impl Application {
389389
let lang_loader = helix_core::config::user_lang_loader()?;
390390

391391
self.editor.syn_loader.store(Arc::new(lang_loader));
392+
let loader = self.editor.syn_loader.load();
392393
for document in self.editor.documents.values_mut() {
393-
document.detect_language(self.editor.syn_loader.clone());
394+
document.detect_language(&loader);
394395
let diagnostics = Editor::doc_diagnostics(
395396
&self.editor.language_servers,
396397
&self.editor.diagnostics,

helix-term/src/commands/typed.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2080,10 +2080,11 @@ fn language(cx: &mut compositor::Context, args: Args, event: PromptEvent) -> any
20802080

20812081
let doc = doc_mut!(cx.editor);
20822082

2083+
let loader = cx.editor.syn_loader.load();
20832084
if &args[0] == DEFAULT_LANGUAGE_NAME {
2084-
doc.set_language(None, None)
2085+
doc.set_language(None, &loader)
20852086
} else {
2086-
doc.set_language_by_language_id(&args[0], cx.editor.syn_loader.clone())?;
2087+
doc.set_language_by_language_id(&args[0], &loader)?;
20872088
}
20882089
doc.detect_indent_and_line_ending();
20892090

helix-term/src/ui/picker.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,14 @@ impl<T: 'static + Send + Sync, D: 'static + Send + Sync> Picker<T, D> {
624624
if content_type.is_binary() {
625625
return Ok(CachedPreview::Binary);
626626
}
627-
Document::open(&path, None, None, editor.config.clone()).map_or(
627+
Document::open(
628+
&path,
629+
None,
630+
false,
631+
editor.config.clone(),
632+
editor.syn_loader.clone(),
633+
)
634+
.map_or(
628635
Err(std::io::Error::new(
629636
std::io::ErrorKind::NotFound,
630637
"Cannot open document",

helix-view/src/document.rs

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,11 @@ pub struct Document {
207207
// NOTE: ideally this would live on the handler for color swatches. This is blocked on a
208208
// large refactor that would make `&mut Editor` available on the `DocumentDidChange` event.
209209
pub color_swatch_controller: TaskController,
210+
211+
// NOTE: this field should eventually go away - we should use the Editor's syn_loader instead
212+
// of storing a copy on every doc. Then we can remove the surrounding `Arc` and use the
213+
// `ArcSwap` directly.
214+
syn_loader: Arc<ArcSwap<syntax::Loader>>,
210215
}
211216

212217
#[derive(Debug, Clone, Default)]
@@ -677,6 +682,7 @@ impl Document {
677682
text: Rope,
678683
encoding_with_bom_info: Option<(&'static Encoding, bool)>,
679684
config: Arc<dyn DynAccess<Config>>,
685+
syn_loader: Arc<ArcSwap<syntax::Loader>>,
680686
) -> Self {
681687
let (encoding, has_bom) = encoding_with_bom_info.unwrap_or((encoding::UTF_8, false));
682688
let line_ending = config.load().default_line_ending.into();
@@ -719,13 +725,17 @@ impl Document {
719725
jump_labels: HashMap::new(),
720726
color_swatches: None,
721727
color_swatch_controller: TaskController::new(),
728+
syn_loader,
722729
}
723730
}
724731

725-
pub fn default(config: Arc<dyn DynAccess<Config>>) -> Self {
732+
pub fn default(
733+
config: Arc<dyn DynAccess<Config>>,
734+
syn_loader: Arc<ArcSwap<syntax::Loader>>,
735+
) -> Self {
726736
let line_ending: LineEnding = config.load().default_line_ending.into();
727737
let text = Rope::from(line_ending.as_str());
728-
Self::from(text, None, config)
738+
Self::from(text, None, config, syn_loader)
729739
}
730740

731741
// TODO: async fn?
@@ -734,8 +744,9 @@ impl Document {
734744
pub fn open(
735745
path: &Path,
736746
mut encoding: Option<&'static Encoding>,
737-
config_loader: Option<Arc<ArcSwap<syntax::Loader>>>,
747+
detect_language: bool,
738748
config: Arc<dyn DynAccess<Config>>,
749+
syn_loader: Arc<ArcSwap<syntax::Loader>>,
739750
) -> Result<Self, DocumentOpenError> {
740751
// If the path is not a regular file (e.g.: /dev/random) it should not be opened.
741752
if path.metadata().is_ok_and(|metadata| !metadata.is_file()) {
@@ -761,12 +772,13 @@ impl Document {
761772
(Rope::from(line_ending.as_str()), encoding, false)
762773
};
763774

764-
let mut doc = Self::from(rope, Some((encoding, has_bom)), config);
775+
let loader = syn_loader.load();
776+
let mut doc = Self::from(rope, Some((encoding, has_bom)), config, syn_loader);
765777

766778
// set the path and try detecting the language
767779
doc.set_path(Some(path));
768-
if let Some(loader) = config_loader {
769-
doc.detect_language(loader);
780+
if detect_language {
781+
doc.detect_language(&loader);
770782
}
771783

772784
doc.editor_config = editor_config;
@@ -1102,12 +1114,8 @@ impl Document {
11021114
}
11031115

11041116
/// Detect the programming language based on the file type.
1105-
pub fn detect_language(&mut self, config_loader: Arc<ArcSwap<syntax::Loader>>) {
1106-
let loader = config_loader.load();
1107-
self.set_language(
1108-
self.detect_language_config(&loader),
1109-
Some(Arc::clone(&config_loader)),
1110-
);
1117+
pub fn detect_language(&mut self, loader: &syntax::Loader) {
1118+
self.set_language(self.detect_language_config(loader), loader);
11111119
}
11121120

11131121
/// Detect the programming language based on the file type.
@@ -1257,34 +1265,33 @@ impl Document {
12571265
pub fn set_language(
12581266
&mut self,
12591267
language_config: Option<Arc<syntax::config::LanguageConfiguration>>,
1260-
loader: Option<Arc<ArcSwap<syntax::Loader>>>,
1268+
loader: &syntax::Loader,
12611269
) {
1262-
if let (Some(language_config), Some(loader)) = (language_config, loader) {
1263-
if let Some(highlight_config) =
1264-
language_config.highlight_config(&(*loader).load().scopes())
1265-
{
1266-
self.syntax = Syntax::new(self.text.slice(..), highlight_config, loader);
1267-
}
1268-
1269-
self.language = Some(language_config);
1270-
} else {
1271-
self.syntax = None;
1272-
self.language = None;
1273-
};
1270+
self.language = language_config;
1271+
self.syntax = self
1272+
.language
1273+
.as_ref()
1274+
.and_then(|config| config.highlight_config(&loader.scopes()))
1275+
.and_then(|highlight_config| {
1276+
Syntax::new(
1277+
self.text.slice(..),
1278+
highlight_config,
1279+
self.syn_loader.clone(),
1280+
)
1281+
});
12741282
}
12751283

12761284
/// Set the programming language for the file if you know the language but don't have the
12771285
/// [`syntax::config::LanguageConfiguration`] for it.
12781286
pub fn set_language_by_language_id(
12791287
&mut self,
12801288
language_id: &str,
1281-
config_loader: Arc<ArcSwap<syntax::Loader>>,
1289+
loader: &syntax::Loader,
12821290
) -> anyhow::Result<()> {
1283-
let language_config = (*config_loader)
1284-
.load()
1291+
let language_config = loader
12851292
.language_config_for_language_id(language_id)
12861293
.ok_or_else(|| anyhow!("invalid language id: {}", language_id))?;
1287-
self.set_language(Some(language_config), Some(config_loader));
1294+
self.set_language(Some(language_config), loader);
12881295
Ok(())
12891296
}
12901297

@@ -2299,6 +2306,7 @@ mod test {
22992306
text,
23002307
None,
23012308
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
2309+
Arc::new(ArcSwap::from_pointee(syntax::Loader::default())),
23022310
);
23032311
let view = ViewId::default();
23042312
doc.set_selection(view, Selection::single(0, 0));
@@ -2337,6 +2345,7 @@ mod test {
23372345
text,
23382346
None,
23392347
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
2348+
Arc::new(ArcSwap::from_pointee(syntax::Loader::default())),
23402349
);
23412350
let view = ViewId::default();
23422351
doc.set_selection(view, Selection::single(5, 5));
@@ -2450,9 +2459,12 @@ mod test {
24502459
#[test]
24512460
fn test_line_ending() {
24522461
assert_eq!(
2453-
Document::default(Arc::new(ArcSwap::new(Arc::new(Config::default()))))
2454-
.text()
2455-
.to_string(),
2462+
Document::default(
2463+
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
2464+
Arc::new(ArcSwap::from_pointee(syntax::Loader::default()))
2465+
)
2466+
.text()
2467+
.to_string(),
24562468
helix_core::NATIVE_LINE_ENDING.as_str()
24572469
);
24582470
}

helix-view/src/editor.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,9 +1474,9 @@ impl Editor {
14741474
}
14751475

14761476
pub fn refresh_doc_language(&mut self, doc_id: DocumentId) {
1477-
let loader = self.syn_loader.clone();
1477+
let loader = self.syn_loader.load();
14781478
let doc = doc_mut!(self, &doc_id);
1479-
doc.detect_language(loader);
1479+
doc.detect_language(&loader);
14801480
doc.detect_editor_config();
14811481
doc.detect_indent_and_line_ending();
14821482
self.refresh_language_servers(doc_id);
@@ -1736,7 +1736,10 @@ impl Editor {
17361736
}
17371737

17381738
pub fn new_file(&mut self, action: Action) -> DocumentId {
1739-
self.new_file_from_document(action, Document::default(self.config.clone()))
1739+
self.new_file_from_document(
1740+
action,
1741+
Document::default(self.config.clone(), self.syn_loader.clone()),
1742+
)
17401743
}
17411744

17421745
pub fn new_file_from_stdin(&mut self, action: Action) -> Result<DocumentId, Error> {
@@ -1745,6 +1748,7 @@ impl Editor {
17451748
helix_core::Rope::default(),
17461749
Some((encoding, has_bom)),
17471750
self.config.clone(),
1751+
self.syn_loader.clone(),
17481752
);
17491753
let doc_id = self.new_file_from_document(action, doc);
17501754
let doc = doc_mut!(self, &doc_id);
@@ -1773,8 +1777,9 @@ impl Editor {
17731777
let mut doc = Document::open(
17741778
&path,
17751779
None,
1776-
Some(self.syn_loader.clone()),
1780+
true,
17771781
self.config.clone(),
1782+
self.syn_loader.clone(),
17781783
)?;
17791784

17801785
let diagnostics =
@@ -1869,7 +1874,12 @@ impl Editor {
18691874
.iter()
18701875
.map(|(&doc_id, _)| doc_id)
18711876
.next()
1872-
.unwrap_or_else(|| self.new_document(Document::default(self.config.clone())));
1877+
.unwrap_or_else(|| {
1878+
self.new_document(Document::default(
1879+
self.config.clone(),
1880+
self.syn_loader.clone(),
1881+
))
1882+
});
18731883
let view = View::new(doc_id, self.config().gutters.clone());
18741884
let view_id = self.tree.insert(view);
18751885
let doc = doc_mut!(self, &doc_id);

helix-view/src/gutter.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ mod tests {
334334
use crate::graphics::Rect;
335335
use crate::DocumentId;
336336
use arc_swap::ArcSwap;
337-
use helix_core::Rope;
337+
use helix_core::{syntax, Rope};
338338

339339
#[test]
340340
fn test_default_gutter_widths() {
@@ -346,6 +346,7 @@ mod tests {
346346
rope,
347347
None,
348348
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
349+
Arc::new(ArcSwap::from_pointee(syntax::Loader::default())),
349350
);
350351

351352
assert_eq!(view.gutters.layout.len(), 5);
@@ -371,6 +372,7 @@ mod tests {
371372
rope,
372373
None,
373374
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
375+
Arc::new(ArcSwap::from_pointee(syntax::Loader::default())),
374376
);
375377

376378
assert_eq!(view.gutters.layout.len(), 1);
@@ -389,6 +391,7 @@ mod tests {
389391
rope,
390392
None,
391393
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
394+
Arc::new(ArcSwap::from_pointee(syntax::Loader::default())),
392395
);
393396

394397
assert_eq!(view.gutters.layout.len(), 2);
@@ -411,13 +414,15 @@ mod tests {
411414
rope,
412415
None,
413416
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
417+
Arc::new(ArcSwap::from_pointee(syntax::Loader::default())),
414418
);
415419

416420
let rope = Rope::from_str("a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np");
417421
let doc_long = Document::from(
418422
rope,
419423
None,
420424
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
425+
Arc::new(ArcSwap::from_pointee(syntax::Loader::default())),
421426
);
422427

423428
assert_eq!(view.gutters.layout.len(), 2);

helix-view/src/view.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ mod tests {
699699

700700
use super::*;
701701
use arc_swap::ArcSwap;
702-
use helix_core::Rope;
702+
use helix_core::{syntax, Rope};
703703

704704
// 1 diagnostic + 1 spacer + 3 linenr (< 1000 lines) + 1 spacer + 1 diff
705705
const DEFAULT_GUTTER_OFFSET: u16 = 7;
@@ -719,6 +719,7 @@ mod tests {
719719
rope,
720720
None,
721721
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
722+
Arc::new(ArcSwap::from_pointee(syntax::Loader::default())),
722723
);
723724
doc.ensure_view_init(view.id);
724725

@@ -894,6 +895,7 @@ mod tests {
894895
rope,
895896
None,
896897
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
898+
Arc::new(ArcSwap::from_pointee(syntax::Loader::default())),
897899
);
898900
doc.ensure_view_init(view.id);
899901
assert_eq!(
@@ -924,6 +926,7 @@ mod tests {
924926
rope,
925927
None,
926928
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
929+
Arc::new(ArcSwap::from_pointee(syntax::Loader::default())),
927930
);
928931
doc.ensure_view_init(view.id);
929932
assert_eq!(
@@ -948,6 +951,7 @@ mod tests {
948951
rope,
949952
None,
950953
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
954+
Arc::new(ArcSwap::from_pointee(syntax::Loader::default())),
951955
);
952956
doc.ensure_view_init(view.id);
953957

@@ -1032,6 +1036,7 @@ mod tests {
10321036
rope,
10331037
None,
10341038
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
1039+
Arc::new(ArcSwap::from_pointee(syntax::Loader::default())),
10351040
);
10361041
doc.ensure_view_init(view.id);
10371042

0 commit comments

Comments
 (0)