|
|
@ -1,4 +1,10 @@
|
|
|
|
use crate::{chars::char_is_line_ending, regex::Regex, Change, Rope, RopeSlice, Transaction};
|
|
|
|
use crate::{
|
|
|
|
|
|
|
|
chars::char_is_line_ending,
|
|
|
|
|
|
|
|
regex::Regex,
|
|
|
|
|
|
|
|
transaction::{ChangeSet, Operation},
|
|
|
|
|
|
|
|
Rope, RopeSlice, Tendril,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
pub use helix_syntax::{get_language, get_language_name, Lang};
|
|
|
|
pub use helix_syntax::{get_language, get_language_name, Lang};
|
|
|
|
|
|
|
|
|
|
|
|
use arc_swap::ArcSwap;
|
|
|
|
use arc_swap::ArcSwap;
|
|
|
@ -8,7 +14,7 @@ use std::{
|
|
|
|
cell::RefCell,
|
|
|
|
cell::RefCell,
|
|
|
|
collections::{HashMap, HashSet},
|
|
|
|
collections::{HashMap, HashSet},
|
|
|
|
fmt,
|
|
|
|
fmt,
|
|
|
|
path::{Path, PathBuf},
|
|
|
|
path::Path,
|
|
|
|
sync::Arc,
|
|
|
|
sync::Arc,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
@ -473,12 +479,6 @@ pub struct LanguageLayer {
|
|
|
|
pub(crate) tree: Option<Tree>,
|
|
|
|
pub(crate) tree: Option<Tree>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
|
|
|
|
coords_at_pos,
|
|
|
|
|
|
|
|
transaction::{ChangeSet, Operation},
|
|
|
|
|
|
|
|
Tendril,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl LanguageLayer {
|
|
|
|
impl LanguageLayer {
|
|
|
|
// pub fn new() -> Self {
|
|
|
|
// pub fn new() -> Self {
|
|
|
|
// Self { tree: None }
|
|
|
|
// Self { tree: None }
|
|
|
@ -1776,135 +1776,141 @@ impl<I: Iterator<Item = HighlightEvent>> Iterator for Merge<I> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(test)]
|
|
|
|
fn test_parser() {
|
|
|
|
mod test {
|
|
|
|
let highlight_names: Vec<String> = [
|
|
|
|
use super::*;
|
|
|
|
"attribute",
|
|
|
|
use crate::{Rope, Transaction};
|
|
|
|
"constant",
|
|
|
|
|
|
|
|
"function.builtin",
|
|
|
|
#[test]
|
|
|
|
"function",
|
|
|
|
fn test_parser() {
|
|
|
|
"keyword",
|
|
|
|
let highlight_names: Vec<String> = [
|
|
|
|
"operator",
|
|
|
|
"attribute",
|
|
|
|
"property",
|
|
|
|
"constant",
|
|
|
|
"punctuation",
|
|
|
|
"function.builtin",
|
|
|
|
"punctuation.bracket",
|
|
|
|
"function",
|
|
|
|
"punctuation.delimiter",
|
|
|
|
"keyword",
|
|
|
|
"string",
|
|
|
|
"operator",
|
|
|
|
"string.special",
|
|
|
|
"property",
|
|
|
|
"tag",
|
|
|
|
"punctuation",
|
|
|
|
"type",
|
|
|
|
"punctuation.bracket",
|
|
|
|
"type.builtin",
|
|
|
|
"punctuation.delimiter",
|
|
|
|
"variable",
|
|
|
|
"string",
|
|
|
|
"variable.builtin",
|
|
|
|
"string.special",
|
|
|
|
"variable.parameter",
|
|
|
|
"tag",
|
|
|
|
]
|
|
|
|
"type",
|
|
|
|
.iter()
|
|
|
|
"type.builtin",
|
|
|
|
.cloned()
|
|
|
|
"variable",
|
|
|
|
.map(String::from)
|
|
|
|
"variable.builtin",
|
|
|
|
.collect();
|
|
|
|
"variable.parameter",
|
|
|
|
|
|
|
|
]
|
|
|
|
let language = get_language(Lang::Rust);
|
|
|
|
.iter()
|
|
|
|
let mut config = HighlightConfiguration::new(
|
|
|
|
.cloned()
|
|
|
|
language,
|
|
|
|
.map(String::from)
|
|
|
|
&std::fs::read_to_string(
|
|
|
|
.collect();
|
|
|
|
"../helix-syntax/languages/tree-sitter-rust/queries/highlights.scm",
|
|
|
|
|
|
|
|
)
|
|
|
|
let language = get_language(Lang::Rust);
|
|
|
|
.unwrap(),
|
|
|
|
let mut config = HighlightConfiguration::new(
|
|
|
|
&std::fs::read_to_string(
|
|
|
|
language,
|
|
|
|
"../helix-syntax/languages/tree-sitter-rust/queries/injections.scm",
|
|
|
|
&std::fs::read_to_string(
|
|
|
|
)
|
|
|
|
"../helix-syntax/languages/tree-sitter-rust/queries/highlights.scm",
|
|
|
|
.unwrap(),
|
|
|
|
)
|
|
|
|
"", // locals.scm
|
|
|
|
.unwrap(),
|
|
|
|
)
|
|
|
|
&std::fs::read_to_string(
|
|
|
|
.unwrap();
|
|
|
|
"../helix-syntax/languages/tree-sitter-rust/queries/injections.scm",
|
|
|
|
config.configure(&highlight_names);
|
|
|
|
)
|
|
|
|
|
|
|
|
.unwrap(),
|
|
|
|
let source = Rope::from_str(
|
|
|
|
"", // locals.scm
|
|
|
|
"
|
|
|
|
|
|
|
|
struct Stuff {}
|
|
|
|
|
|
|
|
fn main() {}
|
|
|
|
|
|
|
|
",
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
let syntax = Syntax::new(&source, Arc::new(config));
|
|
|
|
|
|
|
|
let tree = syntax.tree();
|
|
|
|
|
|
|
|
let root = tree.root_node();
|
|
|
|
|
|
|
|
assert_eq!(root.kind(), "source_file");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
|
|
root.to_sexp(),
|
|
|
|
|
|
|
|
concat!(
|
|
|
|
|
|
|
|
"(source_file ",
|
|
|
|
|
|
|
|
"(struct_item name: (type_identifier) body: (field_declaration_list)) ",
|
|
|
|
|
|
|
|
"(function_item name: (identifier) parameters: (parameters) body: (block)))"
|
|
|
|
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
config.configure(&highlight_names);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let source = Rope::from_str(
|
|
|
|
|
|
|
|
"
|
|
|
|
|
|
|
|
struct Stuff {}
|
|
|
|
|
|
|
|
fn main() {}
|
|
|
|
|
|
|
|
",
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
let syntax = Syntax::new(&source, Arc::new(config));
|
|
|
|
|
|
|
|
let tree = syntax.tree();
|
|
|
|
|
|
|
|
let root = tree.root_node();
|
|
|
|
|
|
|
|
assert_eq!(root.kind(), "source_file");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
|
|
root.to_sexp(),
|
|
|
|
|
|
|
|
concat!(
|
|
|
|
|
|
|
|
"(source_file ",
|
|
|
|
|
|
|
|
"(struct_item name: (type_identifier) body: (field_declaration_list)) ",
|
|
|
|
|
|
|
|
"(function_item name: (identifier) parameters: (parameters) body: (block)))"
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
let struct_node = root.child(0).unwrap();
|
|
|
|
let struct_node = root.child(0).unwrap();
|
|
|
|
assert_eq!(struct_node.kind(), "struct_item");
|
|
|
|
assert_eq!(struct_node.kind(), "struct_item");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[test]
|
|
|
|
fn test_input_edits() {
|
|
|
|
fn test_input_edits() {
|
|
|
|
use crate::State;
|
|
|
|
use crate::State;
|
|
|
|
use tree_sitter::InputEdit;
|
|
|
|
use tree_sitter::InputEdit;
|
|
|
|
|
|
|
|
|
|
|
|
let mut state = State::new("hello world!\ntest 123".into());
|
|
|
|
let mut state = State::new("hello world!\ntest 123".into());
|
|
|
|
let transaction = Transaction::change(
|
|
|
|
let transaction = Transaction::change(
|
|
|
|
&state.doc,
|
|
|
|
&state.doc,
|
|
|
|
vec![(6, 11, Some("test".into())), (12, 17, None)].into_iter(),
|
|
|
|
vec![(6, 11, Some("test".into())), (12, 17, None)].into_iter(),
|
|
|
|
);
|
|
|
|
);
|
|
|
|
let edits = LanguageLayer::generate_edits(state.doc.slice(..), transaction.changes());
|
|
|
|
let edits = LanguageLayer::generate_edits(state.doc.slice(..), transaction.changes());
|
|
|
|
// transaction.apply(&mut state);
|
|
|
|
// transaction.apply(&mut state);
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
assert_eq!(
|
|
|
|
edits,
|
|
|
|
edits,
|
|
|
|
&[
|
|
|
|
&[
|
|
|
|
InputEdit {
|
|
|
|
InputEdit {
|
|
|
|
start_byte: 6,
|
|
|
|
start_byte: 6,
|
|
|
|
old_end_byte: 11,
|
|
|
|
old_end_byte: 11,
|
|
|
|
new_end_byte: 10,
|
|
|
|
new_end_byte: 10,
|
|
|
|
start_position: Point { row: 0, column: 6 },
|
|
|
|
start_position: Point { row: 0, column: 6 },
|
|
|
|
old_end_position: Point { row: 0, column: 11 },
|
|
|
|
old_end_position: Point { row: 0, column: 11 },
|
|
|
|
new_end_position: Point { row: 0, column: 10 }
|
|
|
|
new_end_position: Point { row: 0, column: 10 }
|
|
|
|
},
|
|
|
|
},
|
|
|
|
InputEdit {
|
|
|
|
InputEdit {
|
|
|
|
start_byte: 12,
|
|
|
|
start_byte: 12,
|
|
|
|
old_end_byte: 17,
|
|
|
|
old_end_byte: 17,
|
|
|
|
new_end_byte: 12,
|
|
|
|
new_end_byte: 12,
|
|
|
|
start_position: Point { row: 0, column: 12 },
|
|
|
|
start_position: Point { row: 0, column: 12 },
|
|
|
|
old_end_position: Point { row: 1, column: 4 },
|
|
|
|
old_end_position: Point { row: 1, column: 4 },
|
|
|
|
new_end_position: Point { row: 0, column: 12 }
|
|
|
|
new_end_position: Point { row: 0, column: 12 }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
]
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// Testing with the official example from tree-sitter
|
|
|
|
// Testing with the official example from tree-sitter
|
|
|
|
let mut state = State::new("fn test() {}".into());
|
|
|
|
let mut state = State::new("fn test() {}".into());
|
|
|
|
let transaction =
|
|
|
|
let transaction =
|
|
|
|
Transaction::change(&state.doc, vec![(8, 8, Some("a: u32".into()))].into_iter());
|
|
|
|
Transaction::change(&state.doc, vec![(8, 8, Some("a: u32".into()))].into_iter());
|
|
|
|
let edits = LanguageLayer::generate_edits(state.doc.slice(..), transaction.changes());
|
|
|
|
let edits = LanguageLayer::generate_edits(state.doc.slice(..), transaction.changes());
|
|
|
|
transaction.apply(&mut state.doc);
|
|
|
|
transaction.apply(&mut state.doc);
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(state.doc, "fn test(a: u32) {}");
|
|
|
|
assert_eq!(state.doc, "fn test(a: u32) {}");
|
|
|
|
assert_eq!(
|
|
|
|
assert_eq!(
|
|
|
|
edits,
|
|
|
|
edits,
|
|
|
|
&[InputEdit {
|
|
|
|
&[InputEdit {
|
|
|
|
start_byte: 8,
|
|
|
|
start_byte: 8,
|
|
|
|
old_end_byte: 8,
|
|
|
|
old_end_byte: 8,
|
|
|
|
new_end_byte: 14,
|
|
|
|
new_end_byte: 14,
|
|
|
|
start_position: Point { row: 0, column: 8 },
|
|
|
|
start_position: Point { row: 0, column: 8 },
|
|
|
|
old_end_position: Point { row: 0, column: 8 },
|
|
|
|
old_end_position: Point { row: 0, column: 8 },
|
|
|
|
new_end_position: Point { row: 0, column: 14 }
|
|
|
|
new_end_position: Point { row: 0, column: 14 }
|
|
|
|
}]
|
|
|
|
}]
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[test]
|
|
|
|
fn test_load_runtime_file() {
|
|
|
|
fn test_load_runtime_file() {
|
|
|
|
// Test to make sure we can load some data from the runtime directory.
|
|
|
|
// Test to make sure we can load some data from the runtime directory.
|
|
|
|
let contents = load_runtime_file("rust", "indents.toml").unwrap();
|
|
|
|
let contents = load_runtime_file("rust", "indents.toml").unwrap();
|
|
|
|
assert!(!contents.is_empty());
|
|
|
|
assert!(!contents.is_empty());
|
|
|
|
|
|
|
|
|
|
|
|
let results = load_runtime_file("rust", "does-not-exist");
|
|
|
|
let results = load_runtime_file("rust", "does-not-exist");
|
|
|
|
assert!(results.is_err());
|
|
|
|
assert!(results.is_err());
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|