aboutsummaryrefslogtreecommitdiff
path: root/helix-core/tests/indent.rs
blob: 1dec998947383a666a2bb60fbee6e5251931b260 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use helix_core::{
    indent::{indent_level_for_line, treesitter_indent_for_pos, IndentStyle},
    syntax::Loader,
    Syntax,
};
use std::path::PathBuf;

#[test]
fn test_treesitter_indent_rust() {
    test_treesitter_indent("rust.rs", "source.rust");
}
#[test]
fn test_treesitter_indent_rust_2() {
    test_treesitter_indent("indent.rs", "source.rust");
    // TODO Use commands.rs as indentation test.
    // Currently this fails because we can't align the parameters of a closure yet
    // test_treesitter_indent("commands.rs", "source.rust");
}

#[test]
fn test_indent_level_for_line_with_spaces() {
    let tab_width: usize = 4;
    let indent_width: usize = 4;

    let line = ropey::Rope::from_str("        Indented with 8 spaces");

    let indent_level = indent_level_for_line(line.slice(0..), tab_width, indent_width);
    assert_eq!(indent_level, 2)
}

#[test]
fn test_indent_level_for_line_with_tabs() {
    let tab_width: usize = 4;
    let indent_width: usize = 4;

    let line = ropey::Rope::from_str("\t\tIndented with 2 tabs");

    let indent_level = indent_level_for_line(line.slice(0..), tab_width, indent_width);
    assert_eq!(indent_level, 2)
}

#[test]
fn test_indent_level_for_line_with_spaces_and_tabs() {
    let tab_width: usize = 4;
    let indent_width: usize = 4;

    let line = ropey::Rope::from_str("   \t \tIndented with mix of spaces and tabs");

    let indent_level = indent_level_for_line(line.slice(0..), tab_width, indent_width);
    assert_eq!(indent_level, 2)
}

fn test_treesitter_indent(file_name: &str, lang_scope: &str) {
    let mut test_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    test_dir.push("tests/data/indent");

    let mut test_file = test_dir.clone();
    test_file.push(file_name);
    let test_file = std::fs::File::open(test_file).unwrap();
    let doc = ropey::Rope::from_reader(test_file).unwrap();

    let mut config_file = test_dir;
    config_file.push("languages.toml");
    let config = std::fs::read_to_string(config_file).unwrap();
    let config = toml::from_str(&config).unwrap();
    let loader = Loader::new(config);

    // set runtime path so we can find the queries
    let mut runtime = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    runtime.push("../runtime");
    std::env::set_var("HELIX_RUNTIME", runtime.to_str().unwrap());

    let language_config = loader.language_config_for_scope(lang_scope).unwrap();
    let highlight_config = language_config.highlight_config(&[]).unwrap();
    let text = doc.slice(..);
    let syntax = Syntax::new(text, highlight_config, std::sync::Arc::new(loader)).unwrap();
    let indent_query = language_config.indent_query().unwrap();

    for i in 0..doc.len_lines() {
        let line = text.line(i);
        if let Some(pos) = helix_core::find_first_non_whitespace_char(line) {
            let tab_and_indent_width: usize = 4;
            let suggested_indent = treesitter_indent_for_pos(
                indent_query,
                &syntax,
                &IndentStyle::Spaces(tab_and_indent_width as u8),
                tab_and_indent_width,
                tab_and_indent_width,
                text,
                i,
                text.line_to_char(i) + pos,
                false,
            )
            .unwrap();
            assert!(
                line.get_slice(..pos).map_or(false, |s| s == suggested_indent),
                "Wrong indentation on line {}:\n\"{}\" (original line)\n\"{}\" (suggested indentation)\n",
                i+1,
                line.slice(..line.len_chars()-1),
                suggested_indent,
            );
        }
    }
}