From bad6034ba5927316b43d3eb57a2a1749c655f218 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Sun, 24 May 2026 10:11:06 +0200 Subject: [PATCH] Working goto with mist --- crates/analyzer/src/lib.rs | 92 +++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/crates/analyzer/src/lib.rs b/crates/analyzer/src/lib.rs index 0c2f8b9..b42ddd2 100644 --- a/crates/analyzer/src/lib.rs +++ b/crates/analyzer/src/lib.rs @@ -2,11 +2,12 @@ pub mod builder; pub mod rust_analyzer; pub mod transpiler; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::fs; use std::path::{Component, PathBuf}; use std::sync::Arc; +use mist_parser::rev_mapper; use tokio::sync::Mutex; use tower_lsp::jsonrpc::Result; use tower_lsp::lsp_types::notification::Notification; @@ -22,6 +23,7 @@ struct Backend { workspace_folder: Arc>>, previous_diagnostics: Arc>>>, rust_analyzer: Arc>, + mapping: Arc>>>, } /// Helper function to force percent-encoding on Windows drive colons @@ -45,6 +47,40 @@ fn clean_lsp_url(path: &std::path::Path) -> Option { Url::parse(&url_str).ok() } +impl Backend { + async fn get_mist_location(&self, rs_loc: Location) -> Location { + let rs_path = rs_loc.uri.to_file_path().unwrap(); + + match self.mapping.lock().await.get(&rs_path) { + Some(mapping) => { + let (_, rev_mapper::MistMap(line, character)) = rev_mapper::find_mapping( + mapping, + &rev_mapper::RustMap( + rs_loc.range.start.line as usize, + rs_loc.range.start.character as usize, + ), + ) + .expect("Failed to map"); + + Location { + uri: Url::from_file_path(from_rust_to_mist(rs_path)).unwrap(), + range: Range { + start: Position { + line: line as u32 - 1, + character: character as u32, + }, + end: Position { + line: line as u32 - 1, + character: character as u32 + 1, + }, + }, + } + } + None => rs_loc, + } + } +} + #[tower_lsp::async_trait] impl LanguageServer for Backend { async fn initialize(&self, params: InitializeParams) -> Result { @@ -208,10 +244,14 @@ impl LanguageServer for Backend { params.text_document.text = transpiler::transpile_text(¶ms.text_document.text).unwrap(); - params.text_document.uri = Url::from_file_path(from_mist_to_rust( - params.text_document.uri.to_file_path().unwrap(), - )) - .unwrap(); + let rust_path = from_mist_to_rust(params.text_document.uri.to_file_path().unwrap()); + + params.text_document.uri = Url::from_file_path(&rust_path).unwrap(); + + self.mapping.lock().await.insert( + rust_path, + rev_mapper::get_mapping(¶ms.text_document.text), + ); } self.rust_analyzer @@ -271,7 +311,18 @@ impl LanguageServer for Backend { eprintln!("{:?}", rs_res); - Ok(rs_res) + Ok(match rs_res { + Some(GotoDefinitionResponse::Array(mut arr)) => { + for rs_loc in &mut arr { + let a = self.get_mist_location(rs_loc.clone()).await; + + *rs_loc = a; + } + + Some(GotoDefinitionResponse::Array(arr)) + } + _ => rs_res, + }) } } @@ -284,6 +335,7 @@ pub async fn start() { client, workspace_folder: Arc::new(Mutex::new(None)), previous_diagnostics: Arc::new(Mutex::new(HashMap::new())), + mapping: Arc::new(Mutex::new(HashMap::new())), rust_analyzer: Arc::new(Mutex::new( RustAnalyzer::new().expect("Failed to create rust analyzer"), )), @@ -305,6 +357,34 @@ pub fn from_mist_to_rust(mut path: PathBuf) -> PathBuf { } } +pub fn from_rust_to_mist(mut path: PathBuf) -> PathBuf { + // reverse extension + path.set_extension("mist"); + + let comps: Vec = path.components().collect(); + + // pattern we originally inserted: ".mist/lsp" + let pattern: Vec = std::path::Path::new(".mist/lsp").components().collect(); + + // find the last occurrence of the pattern + if let Some(pos) = comps + .windows(pattern.len()) + .rposition(|window| window == pattern.as_slice()) + { + let mut new_comps = comps.clone(); + + // replace the matched range with "src" + new_comps.splice( + pos..pos + pattern.len(), + std::iter::once(Component::Normal(std::ffi::OsStr::new("src"))), + ); + + new_comps.iter().collect() + } else { + path + } +} + fn insert_at_position(s: &str, line: usize, col: usize, insert: &str) -> String { let mut lines: Vec = s.lines().map(|l| l.to_string()).collect();