From e5509e89a4cd1f49d9cecb8442b8a61810162969 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Fri, 26 Jun 2026 01:02:01 +0200 Subject: [PATCH] Working formatter #90 --- crates/analyzer/src/lib.rs | 57 +++++++++++++++++++++++++++-- crates/analyzer/src/transpiler.rs | 11 ++++++ mist-test/src/items/class_test.mist | 31 ++++------------ 3 files changed, 72 insertions(+), 27 deletions(-) diff --git a/crates/analyzer/src/lib.rs b/crates/analyzer/src/lib.rs index 4e95b1f..7a7b835 100644 --- a/crates/analyzer/src/lib.rs +++ b/crates/analyzer/src/lib.rs @@ -16,14 +16,33 @@ use tower_lsp::lsp_types::{self, *}; use tower_lsp::{Client, LanguageServer, LspService, Server}; use crate::rust_analyzer::RustAnalyzer; -use crate::transpiler::{TranspileError, transpile_mist, transpile_mist_no_sem}; +use crate::transpiler::{TranspileError, format_mist, transpile_mist, transpile_mist_no_sem}; static MARKER_COUNTER: AtomicU64 = AtomicU64::new(0); const KEYWORDS: [&'static str; 22] = [ - "if", "else", "for", "while", "match", "return", "break", "continue ", "struct ", "enum ", - "class ", "trait ", "impl ", "pub ", "mut ", "let ", "dyn ", "loop", "unsafe", - "override", "module ", "void ", + "if", + "else", + "for", + "while", + "match", + "return", + "break", + "continue ", + "struct ", + "enum ", + "class ", + "trait ", + "impl ", + "pub ", + "mut ", + "let ", + "dyn ", + "loop", + "unsafe", + "override", + "module ", + "void ", ]; fn keyword_completion_items() -> impl Iterator { @@ -666,6 +685,8 @@ impl LanguageServer for Backend { }, )); + res.capabilities.document_formatting_provider = Some(OneOf::Left(true)); + res.capabilities.completion_provider = Some(CompletionOptions { resolve_provider: Some(false), trigger_characters: Some(vec![ @@ -1256,6 +1277,34 @@ impl LanguageServer for Backend { } } } + + async fn formatting( + &self, + params: DocumentFormattingParams, + ) -> tower_lsp::jsonrpc::Result>> { + let mist_path = params + .text_document + .uri + .to_file_path() + .map_err(|_| tower_lsp::jsonrpc::Error::internal_error())?; + + let docs = self.documents.lock().await; + + let old_text = docs + .get(&mist_path) + .map_or_else(|| Err(tower_lsp::jsonrpc::Error::internal_error()), Ok)?; + + let new_text = format_mist(&old_text.to_string()) + .map_err(|_| tower_lsp::jsonrpc::Error::internal_error())?; + + Ok(Some(vec![TextEdit { + new_text, + range: Range { + start: Position::new(0, 0), + end: Position::new(u32::MAX, u32::MAX), + }, + }])) + } } fn mist_ify_completions(source: &str, pos: &Position, items: &mut Vec) { diff --git a/crates/analyzer/src/transpiler.rs b/crates/analyzer/src/transpiler.rs index 2ffbfed..8413a8e 100644 --- a/crates/analyzer/src/transpiler.rs +++ b/crates/analyzer/src/transpiler.rs @@ -1,5 +1,6 @@ use std::path::{Path, PathBuf}; +use mist_codegen::fmt::MistCodegen; use mist_codegen::RustCodegen; use mist_parser::parse; use mist_parser::rev_mapper::Mapping; @@ -83,3 +84,13 @@ pub fn transpile_mist_no_sem( mapping: codegen.mapping, }) } + +pub fn format_mist(source: &str) -> Result { + let parsed = parse(source).map_err(|e| format!("parse error: {e:?}"))?; + + let mut codegen = MistCodegen::new(); + codegen.generate(parsed.mod_attributes); + let output = codegen.generate(parsed.items); + + Ok(output) +} diff --git a/mist-test/src/items/class_test.mist b/mist-test/src/items/class_test.mist index 9cd2fd0..3c82038 100644 --- a/mist-test/src/items/class_test.mist +++ b/mist-test/src/items/class_test.mist @@ -2,55 +2,40 @@ pub module class_test; pub class Animal { pub String name; - constructor() { self.name = "Rex".to_string(); } - pub String speak(&self) { "Unknown".to_string() - } - - pub void test_speak<'a>(&'a self) { + } pub void test_speak<'a>(&'a self) { assert_eq!(self.speak(), "Woof!"); - } - - pub void static_method() {} -} + } pub void static_method() { + }} pub class Mammal : Animal { constructor() { super = Super::new(); } - pub void args_test(&self, i32 x, str& y) { assert_eq!(x, 10); assert_eq!(y, "hello"); - } -} + }} pub class Dog : Mammal { constructor() { super = Super::new(); } - pub String speak(&self) override(Animal) { "Woof!".to_string() - } - - impl std::fmt::Display { - Result<(), std::fmt::Error> fmt(&self, std::fmt::Formatter<'_> mut& f) { + } implstd::fmt::Display { + Result<(), std::fmt::Error> fmt(&self, std::fmt::Formatter<'_>& mut f) { write!(f, "🐾 {}", self.name) - } - } + } } } pub void run_tests() { let dawg = Dog::new(); - dawg.args_test(10, "hello"); - dawg.test_speak(); - assert_eq!(format!("{dawg}"), "🐾 Rex"); -} +} \ No newline at end of file