wip -- lsp mappings to various types

This commit is contained in:
2025-11-30 20:31:06 -07:00
parent 5db31d087d
commit 06a151ab7e
18 changed files with 640 additions and 255 deletions

View File

@@ -0,0 +1,103 @@
use compiler::Compiler;
use parser::Parser;
use safer_ffi::prelude::*;
use std::io::BufWriter;
use tokenizer::Tokenizer;
#[derive_ReprC]
#[repr(C)]
pub struct FfiToken {
pub tooltip: safer_ffi::String,
pub error: safer_ffi::String,
pub column: i32,
pub length: i32,
pub token_kind: u32,
}
#[derive_ReprC]
#[repr(C)]
pub struct FfiRange {
start_col: u32,
end_col: u32,
start_line: u32,
end_line: u32,
}
impl From<lsp_types::Range> for FfiRange {
fn from(value: lsp_types::Range) -> Self {
Self {
start_col: value.start.character,
end_col: value.end.character,
start_line: value.start.line,
end_line: value.end.line,
}
}
}
#[derive_ReprC]
#[repr(C)]
pub struct FfiDiagnostic {
message: safer_ffi::String,
severity: i32,
range: FfiRange,
}
impl From<lsp_types::Diagnostic> for FfiDiagnostic {
fn from(value: lsp_types::Diagnostic) -> Self {
use lsp_types::*;
Self {
message: value.message.into(),
severity: match value.severity.unwrap_or(DiagnosticSeverity::ERROR) {
DiagnosticSeverity::WARNING => 2,
DiagnosticSeverity::INFORMATION => 3,
DiagnosticSeverity::HINT => 4,
_ => 1,
},
range: value.range.into(),
}
}
}
#[ffi_export]
pub fn free_ffi_token_vec(v: safer_ffi::Vec<FfiToken>) {
drop(v)
}
#[ffi_export]
pub fn free_ffi_diagnostic_vec(v: safer_ffi::Vec<FfiDiagnostic>) {
drop(v)
}
#[ffi_export]
pub fn free_string(s: safer_ffi::String) {
drop(s)
}
/// C# handles strings as UTF16. We do NOT want to allocate that memory in C# because
/// we want to avoid GC. So we pass it to Rust to handle all the memory allocations.
/// This should result in the ability to compile many times without triggering frame drops
/// from the GC from a `GetBytes()` call on a string in C#.
#[ffi_export]
pub fn compile_from_string(input: safer_ffi::slice::Ref<'_, u16>) -> safer_ffi::String {
let mut writer = BufWriter::new(Vec::new());
let tokenizer = Tokenizer::from(String::from_utf16_lossy(input.as_slice()));
let parser = Parser::new(tokenizer);
let compiler = Compiler::new(parser, &mut writer, None);
if !compiler.compile().is_empty() {
return safer_ffi::String::EMPTY;
}
let Ok(compiled_vec) = writer.into_inner() else {
return safer_ffi::String::EMPTY;
};
// Safety: I know the compiler only outputs valid utf8
safer_ffi::String::from(unsafe { String::from_utf8_unchecked(compiled_vec) })
}
#[ffi_export]
pub fn diagnose_source() -> safer_ffi::Vec<FfiDiagnostic> {
vec![].into()
}