Skip to content

Commit 85ce859

Browse files
committed
Add SyntaxSetBuilder to get rid of manual linking
Previously, linking had to be done manually using `link_syntaxes` in order for the syntaxes to work. This change introduces a SyntaxSetBuilder that contains all the methods to add/load syntaxes. When calling `build`, the syntaxes are linked and you get a `SyntaxSet`. This has the nice side effect of separating all the methods that mutate to a separate type and making SyntaxSet immutable.
1 parent 93514bb commit 85ce859

File tree

9 files changed

+152
-130
lines changed

9 files changed

+152
-130
lines changed

benches/highlighting.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,16 @@ fn highlight_file(b: &mut Bencher, file: &str) {
3333
};
3434

3535
// don't load from dump so we don't count lazy regex compilation time
36-
let ps = SyntaxSet::load_defaults_nonewlines();
36+
let ss = SyntaxSet::load_defaults_nonewlines();
3737
let ts = ThemeSet::load_defaults();
3838

39-
let syntax = ps.find_syntax_for_file(path).unwrap().unwrap();
39+
let syntax = ss.find_syntax_for_file(path).unwrap().unwrap();
4040
let mut f = File::open(path).unwrap();
4141
let mut s = String::new();
4242
f.read_to_string(&mut s).unwrap();
4343

4444
b.iter(|| {
45-
do_highlight(&s, &ps, syntax, &ts.themes["base16-ocean.dark"])
45+
do_highlight(&s, &ss, syntax, &ts.themes["base16-ocean.dark"])
4646
});
4747
}
4848

benches/loading.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ extern crate criterion;
33
extern crate syntect;
44

55
use criterion::{Bencher, Criterion};
6-
use syntect::parsing::SyntaxSet;
6+
use syntect::parsing::{SyntaxSet, SyntaxSetBuilder};
77
use syntect::highlighting::ThemeSet;
88

99

@@ -27,16 +27,16 @@ fn bench_load_theme(b: &mut Bencher) {
2727

2828
fn bench_load_syntaxes(b: &mut Bencher) {
2929
b.iter(|| {
30-
let mut ps = SyntaxSet::new();
31-
ps.load_syntaxes("testdata/Packages", false).unwrap()
30+
let mut builder = SyntaxSetBuilder::new();
31+
builder.load_syntaxes("testdata/Packages", false).unwrap()
3232
});
3333
}
3434

3535
fn bench_link_syntaxes(b: &mut Bencher) {
36-
let mut ps = SyntaxSet::new();
37-
ps.load_syntaxes("testdata/Packages", false).unwrap();
36+
let mut builder = SyntaxSetBuilder::new();
37+
builder.load_syntaxes("testdata/Packages", false).unwrap();
3838
b.iter(|| {
39-
ps.link_syntaxes();
39+
builder.clone().build();
4040
});
4141
}
4242

examples/gendata.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! Although it is a valid example for serializing syntaxes, you probably won't need
44
//! to do this yourself unless you want to cache your own compiled grammars.
55
extern crate syntect;
6-
use syntect::parsing::SyntaxSet;
6+
use syntect::parsing::SyntaxSetBuilder;
77
use syntect::highlighting::ThemeSet;
88
use syntect::dumps::*;
99
use std::env;
@@ -22,16 +22,17 @@ fn main() {
2222
Some(ref package_dir),
2323
Some(ref packpath_newlines),
2424
Some(ref packpath_nonewlines)) if cmd == "synpack" => {
25-
let mut ps = SyntaxSet::new();
26-
ps.load_plain_text_syntax();
27-
ps.load_syntaxes(package_dir, true).unwrap();
28-
dump_to_file(&ps, packpath_newlines).unwrap();
29-
30-
ps = SyntaxSet::new();
31-
ps.load_plain_text_syntax();
32-
ps.load_syntaxes(package_dir, false).unwrap();
33-
dump_to_file(&ps, packpath_nonewlines).unwrap();
25+
let mut builder = SyntaxSetBuilder::new();
26+
builder.load_plain_text_syntax();
27+
builder.load_syntaxes(package_dir, true).unwrap();
28+
let ss = builder.build();
29+
dump_to_file(&ss, packpath_newlines).unwrap();
3430

31+
let mut builder_nonewlines = SyntaxSetBuilder::new();
32+
builder_nonewlines.load_plain_text_syntax();
33+
builder_nonewlines.load_syntaxes(package_dir, false).unwrap();
34+
let ss_nonewlines = builder_nonewlines.build();
35+
dump_to_file(&ss_nonewlines, packpath_nonewlines).unwrap();
3536
}
3637
(Some(ref s), Some(ref theme_dir), Some(ref packpath), None) if s == "themepack" => {
3738
let ts = ThemeSet::load_from_folder(theme_dir).unwrap();

examples/syncat.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,9 @@ fn main() {
5757
};
5858

5959
if let Some(folder) = matches.opt_str("extra-syntaxes") {
60-
ss.load_syntaxes(folder, !no_newlines).unwrap();
61-
ss.link_syntaxes();
60+
let mut builder = ss.builder();
61+
builder.load_syntaxes(folder, !no_newlines).unwrap();
62+
ss = builder.build();
6263
}
6364

6465
let ts = ThemeSet::load_defaults();

examples/syntest.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ extern crate lazy_static;
1414
extern crate regex;
1515
extern crate getopts;
1616

17-
//extern crate onig;
18-
use syntect::parsing::{SyntaxSet, ParseState, ScopeStack, Scope};
17+
use syntect::parsing::{SyntaxSet, SyntaxSetBuilder, ParseState, ScopeStack, Scope};
1918
use syntect::highlighting::ScopeSelectors;
2019
use syntect::easy::{ScopeRegionIterator};
2120

@@ -305,8 +304,9 @@ fn main() {
305304
};
306305
if !syntaxes_path.is_empty() {
307306
println!("loading syntax definitions from {}", syntaxes_path);
308-
ss.load_syntaxes(&syntaxes_path, true).unwrap(); // note that we load the version with newlines
309-
ss.link_syntaxes();
307+
let mut builder = SyntaxSetBuilder::new();
308+
builder.load_syntaxes(&syntaxes_path, true).unwrap(); // note that we load the version with newlines
309+
ss = builder.build();
310310
}
311311

312312
let out_opts = OutputOptions {

src/dumps.rs

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pub fn from_dump_file<T: DeserializeOwned, P: AsRef<Path>>(path: P) -> Result<T>
8080
#[cfg(all(feature = "parsing", feature = "assets", any(feature = "dump-load", feature = "dump-load-rs")))]
8181
impl SyntaxSet {
8282
/// Instantiates a new syntax set from a binary dump of
83-
/// Sublime Text's default open source syntax definitions and then links it.
83+
/// Sublime Text's default open source syntax definitions.
8484
/// These dumps are included in this library's binary for convenience.
8585
///
8686
/// This method loads the version for parsing line strings with no `\n` characters at the end.
@@ -90,24 +90,21 @@ impl SyntaxSet {
9090
/// This is the recommended way of creating a syntax set for
9191
/// non-advanced use cases. It is also significantly faster than loading the YAML files.
9292
///
93-
/// Note that you can load additional syntaxes after doing this,
94-
/// you'll just have to link again. If you want you can even
95-
/// use the fact that SyntaxDefinitions are serializable with
93+
/// Note that you can load additional syntaxes after doing this. If you want
94+
/// you can even use the fact that SyntaxDefinitions are serializable with
9695
/// the bincode crate to cache dumps of additional syntaxes yourself.
9796
pub fn load_defaults_nonewlines() -> SyntaxSet {
98-
let mut ps: SyntaxSet = from_binary(include_bytes!("../assets/default_nonewlines.\
97+
let ss: SyntaxSet = from_binary(include_bytes!("../assets/default_nonewlines.\
9998
packdump"));
100-
ps.link_syntaxes();
101-
ps
99+
ss
102100
}
103101

104102
/// Same as `load_defaults_nonewlines` but for parsing line strings with newlines at the end.
105103
/// These are separate methods because thanks to linker garbage collection, only the serialized
106104
/// dumps for the method(s) you call will be included in the binary (each is ~200kb for now).
107105
pub fn load_defaults_newlines() -> SyntaxSet {
108-
let mut ps: SyntaxSet = from_binary(include_bytes!("../assets/default_newlines.packdump"));
109-
ps.link_syntaxes();
110-
ps
106+
let ss: SyntaxSet = from_binary(include_bytes!("../assets/default_newlines.packdump"));
107+
ss
111108
}
112109
}
113110

@@ -130,29 +127,32 @@ mod tests {
130127
#[test]
131128
fn can_dump_and_load() {
132129
use super::*;
133-
use parsing::SyntaxSet;
134-
let mut ps = SyntaxSet::new();
135-
ps.load_syntaxes("testdata/Packages", false).unwrap();
130+
use parsing::SyntaxSetBuilder;
131+
let mut builder = SyntaxSetBuilder::new();
132+
builder.load_syntaxes("testdata/Packages", false).unwrap();
133+
let ss = builder.build();
136134

137-
let bin = dump_binary(&ps);
135+
let bin = dump_binary(&ss);
138136
println!("{:?}", bin.len());
139-
let ps2: SyntaxSet = from_binary(&bin[..]);
140-
assert_eq!(ps.syntaxes().len(), ps2.syntaxes().len());
137+
let ss2: SyntaxSet = from_binary(&bin[..]);
138+
assert_eq!(ss.syntaxes().len(), ss2.syntaxes().len());
141139
}
142140

143141
#[cfg(all(feature = "yaml-load", any(feature = "dump-create", feature = "dump-create-rs"), any(feature = "dump-load", feature = "dump-load-rs")))]
144142
#[test]
145143
fn dump_is_deterministic() {
146144
use super::*;
147-
use parsing::SyntaxSet;
145+
use parsing::SyntaxSetBuilder;
148146

149-
let mut ps1 = SyntaxSet::new();
150-
ps1.load_syntaxes("testdata/Packages", false).unwrap();
151-
let bin1 = dump_binary(&ps1);
147+
let mut builder1 = SyntaxSetBuilder::new();
148+
builder1.load_syntaxes("testdata/Packages", false).unwrap();
149+
let ss1 = builder1.build();
150+
let bin1 = dump_binary(&ss1);
152151

153-
let mut ps2 = SyntaxSet::new();
154-
ps2.load_syntaxes("testdata/Packages", false).unwrap();
155-
let bin2 = dump_binary(&ps2);
152+
let mut builder2 = SyntaxSetBuilder::new();
153+
builder2.load_syntaxes("testdata/Packages", false).unwrap();
154+
let ss2 = builder2.build();
155+
let bin2 = dump_binary(&ss2);
156156
assert_eq!(bin1, bin2);
157157
}
158158

src/parsing/parser.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ impl<'a> ParseState<'a> {
643643
#[cfg(test)]
644644
mod tests {
645645
use super::*;
646-
use parsing::{SyntaxSet, Scope, ScopeStack};
646+
use parsing::{SyntaxSet, SyntaxSetBuilder, Scope, ScopeStack};
647647
use parsing::ScopeStackOp::{Push, Pop, Clear, Restore};
648648
use util::debug_print_ops;
649649

@@ -1334,9 +1334,9 @@ contexts:
13341334
fn expect_scope_stacks_with_syntax(line: &str, expect: &[&str], syntax: SyntaxDefinition) {
13351335
// check that each expected scope stack appears at least once while parsing the given test line
13361336

1337-
let mut syntax_set = SyntaxSet::new();
1338-
syntax_set.add_syntax(syntax);
1339-
syntax_set.link_syntaxes();
1337+
let mut builder = SyntaxSetBuilder::new();
1338+
builder.add_syntax(syntax);
1339+
let syntax_set = builder.build();
13401340

13411341
let mut state = ParseState::new(&syntax_set, &syntax_set.syntaxes()[0]);
13421342

src/parsing/syntax_definition.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ pub struct Context {
5353
/// This is filled in by the linker at link time
5454
/// for contexts that have `meta_include_prototype==true`
5555
/// and are not included from the prototype.
56-
#[serde(skip_serializing, skip_deserializing)]
5756
pub prototype: Option<ContextId>,
5857
pub uses_backrefs: bool,
5958

0 commit comments

Comments
 (0)