diff --git a/crates/analyzer/src/lib.rs b/crates/analyzer/src/lib.rs index c158aad..886d771 100644 --- a/crates/analyzer/src/lib.rs +++ b/crates/analyzer/src/lib.rs @@ -2,6 +2,7 @@ pub mod builder; pub mod transpiler; use std::collections::HashMap; +use std::fs; use std::path::{Component, PathBuf}; use std::sync::Arc; @@ -55,6 +56,8 @@ impl LanguageServer for Backend { }, )); + res.capabilities.definition_provider = Some(OneOf::Left(true)); + let folder_path = params .workspace_folders .as_ref() @@ -81,6 +84,10 @@ impl LanguageServer for Backend { .await; } + async fn shutdown(&self) -> Result<()> { + Ok(()) + } + async fn did_save(&self, _: DidSaveTextDocumentParams) { self.client .log_message(MessageType::INFO, "Processing did_save event") @@ -173,8 +180,38 @@ impl LanguageServer for Backend { *self.previous_diagnostics.lock().await = diagnostics; } - async fn shutdown(&self) -> Result<()> { - Ok(()) + async fn goto_definition( + &self, + params: GotoDefinitionParams, + ) -> Result> { + let mut source = fs::read_to_string( + params + .text_document_position_params + .text_document + .uri + .to_file_path() + .unwrap(), + ) + .expect("Failed to read source"); + + let inject = "__mist_23"; + + source = insert_at_position( + &source, + params.text_document_position_params.position.line as usize, + params.text_document_position_params.position.character as usize, + &inject, + ); + + let output = transpiler::transpile_text(&source).expect("Failed to transpile"); + + let position = output.find(inject).expect("Didn't find injection").saturating_sub(1); + + self.client + .log_message(MessageType::INFO, format!("Found at {position}")) + .await; + + Ok(None) } } @@ -204,3 +241,29 @@ pub fn from_mist_to_rust(mut path: PathBuf) -> PathBuf { 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(); + + // Convert to 0-index + let line_idx = line.saturating_sub(1); + let col_idx = col.saturating_sub(1); + + // Ensure line exists (optional behavior: extend with empty lines) + if line_idx >= lines.len() { + lines.resize(line_idx + 1, String::new()); + } + + let target = &mut lines[line_idx]; + + // Clamp column to valid char boundary + let char_idx = target + .char_indices() + .nth(col_idx) + .map(|(i, _)| i) + .unwrap_or(target.len()); // if past end, append + + target.insert_str(char_idx, insert); + + lines.join("\n") +} diff --git a/crates/analyzer/src/transpiler.rs b/crates/analyzer/src/transpiler.rs index 36f5049..0e51b31 100644 --- a/crates/analyzer/src/transpiler.rs +++ b/crates/analyzer/src/transpiler.rs @@ -3,7 +3,7 @@ use std::{ path::{Path, PathBuf}, }; -use mist_parser::error::ParseError; +use mist_parser::{ast::TopLevel, error::ParseError}; pub fn build(root: &PathBuf) { let src_dir = root.join("src"); @@ -144,6 +144,12 @@ pub fn transpile_file(path: &Path, output_path: &Path) -> Result<(), String> { Ok(()) } +pub fn transpile_text<'a>(source: &'a str) -> Result>> { + let mut gc = mist_codegen::RustCodegen::new(); + + Ok(gc.generate(mist_parser::parse(&source)?)) +} + fn should_skip(source: &Path, output: &Path) -> bool { if let (Ok(src_meta), Ok(out_meta)) = (fs::metadata(source), fs::metadata(output)) { if let (Ok(src_time), Ok(out_time)) = (src_meta.modified(), out_meta.modified()) {