highlight: Fix logic for handling empty injections with no highlights

This commit is contained in:
Max Brunsfeld 2020-01-27 12:32:37 -08:00
parent 8dd68c360a
commit 3f109a3cb5
6 changed files with 84 additions and 33 deletions

View file

@ -31,13 +31,17 @@ pub fn get_language_queries_path(language_name: &str) -> PathBuf {
pub fn get_highlight_config(
language_name: &str,
injection_query_filename: &str,
injection_query_filename: Option<&str>,
highlight_names: &[String],
) -> HighlightConfiguration {
let language = get_language(language_name);
let queries_path = get_language_queries_path(language_name);
let highlights_query = fs::read_to_string(queries_path.join("highlights.scm")).unwrap();
let injections_query = fs::read_to_string(queries_path.join(injection_query_filename)).unwrap();
let injections_query = if let Some(injection_query_filename) = injection_query_filename {
fs::read_to_string(queries_path.join(injection_query_filename)).unwrap()
} else {
String::new()
};
let locals_query = fs::read_to_string(queries_path.join("locals.scm")).unwrap_or(String::new());
let mut result = HighlightConfiguration::new(
language,

View file

@ -9,15 +9,21 @@ use tree_sitter_highlight::{
lazy_static! {
static ref JS_HIGHLIGHT: HighlightConfiguration =
get_highlight_config("javascript", "injections.scm", &HIGHLIGHT_NAMES);
get_highlight_config("javascript", Some("injections.scm"), &HIGHLIGHT_NAMES);
static ref JSDOC_HIGHLIGHT: HighlightConfiguration =
get_highlight_config("jsdoc", None, &HIGHLIGHT_NAMES);
static ref HTML_HIGHLIGHT: HighlightConfiguration =
get_highlight_config("html", "injections.scm", &HIGHLIGHT_NAMES);
static ref EJS_HIGHLIGHT: HighlightConfiguration =
get_highlight_config("embedded-template", "injections-ejs.scm", &HIGHLIGHT_NAMES);
get_highlight_config("html", Some("injections.scm"), &HIGHLIGHT_NAMES);
static ref EJS_HIGHLIGHT: HighlightConfiguration = get_highlight_config(
"embedded-template",
Some("injections-ejs.scm"),
&HIGHLIGHT_NAMES
);
static ref RUST_HIGHLIGHT: HighlightConfiguration =
get_highlight_config("rust", "injections.scm", &HIGHLIGHT_NAMES);
get_highlight_config("rust", Some("injections.scm"), &HIGHLIGHT_NAMES);
static ref HIGHLIGHT_NAMES: Vec<String> = [
"attribute",
"comment",
"constant",
"constructor",
"function.builtin",
@ -351,6 +357,36 @@ fn test_highlighting_ejs_with_html_and_javascript() {
);
}
#[test]
fn test_highlighting_javascript_with_jsdoc() {
// Regression test: the middle comment has no highlights. This should not prevent
// later injections from highlighting properly.
let source = vec!["a /* @see a */ b; /* nothing */ c; /* @see b */"].join("\n");
assert_eq!(
&to_token_vector(&source, &JS_HIGHLIGHT).unwrap(),
&[[
("a", vec!["variable"]),
(" ", vec![]),
("/* ", vec!["comment"]),
("@see", vec!["comment", "tag"]),
(" a */", vec!["comment"]),
(" ", vec![]),
("b", vec!["variable"]),
(";", vec!["punctuation.delimiter"]),
(" ", vec![]),
("/* nothing */", vec!["comment"]),
(" ", vec![]),
("c", vec!["variable"]),
(";", vec!["punctuation.delimiter"]),
(" ", vec![]),
("/* ", vec!["comment"]),
("@see", vec!["comment", "tag"]),
(" b */", vec!["comment"])
]],
);
}
#[test]
fn test_highlighting_with_content_children_included() {
let source = vec!["assert!(", " a.b.c() < D::e::<F>()", ");"].join("\n");
@ -562,6 +598,7 @@ fn test_language_for_injection_string<'a>(string: &str) -> Option<&'a HighlightC
"javascript" => Some(&JS_HIGHLIGHT),
"html" => Some(&HTML_HIGHLIGHT),
"rust" => Some(&RUST_HIGHLIGHT),
"jsdoc" => Some(&JSDOC_HIGHLIGHT),
_ => None,
}
}

View file

@ -8,7 +8,7 @@ fn test_highlight_test_with_basic_test() {
let language = get_language("javascript");
let config = get_highlight_config(
"javascript",
"injections.scm",
Some("injections.scm"),
&[
"function".to_string(),
"variable.parameter".to_string(),

View file

@ -570,37 +570,45 @@ where
}
fn sort_layers(&mut self) {
if let Some(sort_key) = self.layers[0].sort_key() {
let mut i = 0;
while i + 1 < self.layers.len() {
if let Some(next_offset) = self.layers[i + 1].sort_key() {
if next_offset < sort_key {
i += 1;
continue;
while !self.layers.is_empty() {
if let Some(sort_key) = self.layers[0].sort_key() {
let mut i = 0;
while i + 1 < self.layers.len() {
if let Some(next_offset) = self.layers[i + 1].sort_key() {
if next_offset < sort_key {
i += 1;
continue;
}
}
break;
}
if i > 0 {
&self.layers[0..(i + 1)].rotate_left(1);
}
break;
} else {
let layer = self.layers.remove(0);
self.highlighter.cursors.push(layer.cursor);
}
if i > 0 {
&self.layers[0..(i + 1)].rotate_left(1);
}
} else {
let layer = self.layers.remove(0);
self.highlighter.cursors.push(layer.cursor);
}
}
fn insert_layer(&mut self, mut layer: HighlightIterLayer<'a>) {
let sort_key = layer.sort_key();
let mut i = 1;
while i < self.layers.len() {
if self.layers[i].sort_key() > sort_key {
self.layers.insert(i, layer);
return;
if let Some(sort_key) = layer.sort_key() {
let mut i = 1;
while i < self.layers.len() {
if let Some(sort_key_i) = self.layers[i].sort_key() {
if sort_key_i > sort_key {
self.layers.insert(i, layer);
return;
}
i += 1;
} else {
self.layers.remove(i);
}
}
i += 1;
self.layers.push(layer);
}
self.layers.push(layer);
}
}

View file

@ -24,10 +24,11 @@ fetch_grammar() {
fetch_grammar bash master
fetch_grammar c master
fetch_grammar cpp master
fetch_grammar embedded-template new-highlight-injection-api
fetch_grammar embedded-template master
fetch_grammar go master
fetch_grammar html new-highlight-injection-api
fetch_grammar html master
fetch_grammar javascript master
fetch_grammar jsdoc master
fetch_grammar json master
fetch_grammar python master
fetch_grammar ruby master

View file

@ -3,10 +3,11 @@
call:fetch_grammar bash master
call:fetch_grammar c master
call:fetch_grammar cpp master
call:fetch_grammar embedded-template new-highlight-injection-api
call:fetch_grammar embedded-template master
call:fetch_grammar go master
call:fetch_grammar html new-highlight-injection-api
call:fetch_grammar html master
call:fetch_grammar javascript master
call:fetch_grammar jsdoc master
call:fetch_grammar json master
call:fetch_grammar python master
call:fetch_grammar ruby master