use tower_lsp::lsp_types::*;
use crate::Backend;
use crate::parser::with_parsed_program;
use crate::util::{offset_to_position, position_to_offset};
mod var_definition;
use var_definition::find_variable_definition_in_program;
#[derive(Default)]
pub(super) enum VarDefSearchResult {
#[default]
NotFound,
AtDefinition,
FoundAt { offset: u32, end_offset: u32 },
}
impl Backend {
pub(super) fn resolve_variable_definition(
content: &str,
uri: &str,
position: Position,
var_name: &str,
) -> Option<Location> {
Self::resolve_variable_definition_ast(content, uri, position, var_name)?
}
fn resolve_variable_definition_ast(
content: &str,
uri: &str,
position: Position,
var_name: &str,
) -> Option<Option<Location>> {
let cursor_offset = position_to_offset(content, position);
let result = with_parsed_program(
content,
"resolve_variable_definition_ast",
|program, content| {
find_variable_definition_in_program(program, content, var_name, cursor_offset)
},
);
match result {
VarDefSearchResult::NotFound => {
Some(None)
}
VarDefSearchResult::AtDefinition => {
Some(None)
}
VarDefSearchResult::FoundAt { offset, end_offset } => {
let target_uri = Url::parse(uri).ok()?;
let start_pos = offset_to_position(content, offset as usize);
let end_pos = offset_to_position(content, end_offset as usize);
Some(Some(Location {
uri: target_uri,
range: Range {
start: start_pos,
end: end_pos,
},
}))
}
}
}
}
#[cfg(test)]
mod tests;