emmylua_codestyle/
lib.rs

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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
mod test;

use std::ffi::{CStr, CString};

#[repr(C)]
struct CLibRangeFormatResult {
    pub start_line: i32,
    pub start_col: i32,
    pub end_line: i32,
    pub end_col: i32,
    pub text: *mut libc::c_char,
}

#[derive(Debug)]
pub struct RangeFormatResult {
    pub start_line: i32,
    pub start_col: i32,
    pub end_line: i32,
    pub end_col: i32,
    pub text: String,
}

#[derive(Debug)]
pub struct CodeStyleDiagnostic {
    pub start_line: i32,
    pub start_col: i32,
    pub end_line: i32,
    pub end_col: i32,
    pub message: String,
}

extern "C" {
    fn ReformatLuaCode(code: *const libc::c_char, uri: *const libc::c_char) -> *mut libc::c_char;
    fn RangeFormatLuaCode(
        code: *const libc::c_char,
        uri: *const libc::c_char,
        startLine: i32,
        startCol: i32,
        endLine: i32,
        endCol: i32,
    ) -> CLibRangeFormatResult;
    fn FreeReformatResult(ptr: *mut libc::c_char);
    fn UpdateCodeStyle(workspaceUri: *const libc::c_char, configPath: *const libc::c_char);
    fn RemoveCodeStyle(workspaceUri: *const libc::c_char);
    fn CheckCodeStyle(code: *const libc::c_char, uri: *const libc::c_char) -> *mut libc::c_char;
}

pub fn reformat_code(code: &str, uri: &str) -> String {
    let c_code = CString::new(code).unwrap();
    let c_uri = CString::new(uri).unwrap();
    let c_result = unsafe { ReformatLuaCode(c_code.as_ptr(), c_uri.as_ptr()) };
    let result = unsafe { CStr::from_ptr(c_result).to_string_lossy().into_owned() };
    unsafe { FreeReformatResult(c_result) };
    result
}

pub fn range_format_code(
    code: &str,
    uri: &str,
    start_line: i32,
    start_col: i32,
    end_line: i32,
    end_col: i32,
) -> RangeFormatResult {
    let c_code = CString::new(code).unwrap();
    let c_uri = CString::new(uri).unwrap();
    let c_result = unsafe {
        RangeFormatLuaCode(
            c_code.as_ptr(),
            c_uri.as_ptr(),
            start_line,
            start_col,
            end_line,
            end_col,
        )
    };

    let result = RangeFormatResult {
        start_line: c_result.start_line,
        start_col: c_result.start_col,
        end_line: c_result.end_line,
        end_col: c_result.end_col,
        text: unsafe { CStr::from_ptr(c_result.text).to_string_lossy().into_owned() },
    };
    unsafe { FreeReformatResult(c_result.text) };

    result
}

pub fn update_code_style(workspace_uri: &str, config_path: &str) {
    let c_workspace_uri = CString::new(workspace_uri).unwrap();
    let c_config_path = CString::new(config_path).unwrap();
    unsafe { UpdateCodeStyle(c_workspace_uri.as_ptr(), c_config_path.as_ptr()) };
}

pub fn remove_code_style(workspace_uri: &str) {
    let c_workspace_uri = CString::new(workspace_uri).unwrap();
    unsafe { RemoveCodeStyle(c_workspace_uri.as_ptr()) };
}

pub fn check_code_style(uri: &str, code: &str) -> Vec<CodeStyleDiagnostic> {
    let c_uri = CString::new(uri).unwrap();
    let c_code = CString::new(code).unwrap();
    let c_result = unsafe { CheckCodeStyle(c_code.as_ptr(), c_uri.as_ptr()) };
    if c_result.is_null() {
        return vec![];
    }
    let result = unsafe { CStr::from_ptr(c_result).to_string_lossy().into_owned() };
    unsafe { FreeReformatResult(c_result) };
    // the format is start_line|start_col|end_line|end_col|message \n
    let result = result
        .split("\n")
        .map(|line| {
            let parts: Vec<&str> = line.split("|").collect();
            if parts.len() == 5 {
                Some(CodeStyleDiagnostic {
                    start_line: parts[0].parse().unwrap(),
                    start_col: parts[1].parse().unwrap(),
                    end_line: parts[2].parse().unwrap(),
                    end_col: parts[3].parse().unwrap(),
                    message: parts[4].to_string(),
                })
            } else {
                None
            }
        })
        .filter_map(|x| x)
        .collect::<Vec<CodeStyleDiagnostic>>();

    result
}