semantic_code_edit_mcp/languages/
rust.rs

1use super::{LanguageCommon, LanguageName, traits::LanguageEditor};
2use anyhow::{Result, anyhow};
3use std::{
4    io::{Read, Write},
5    process::{Command, Stdio},
6};
7
8pub fn language() -> Result<LanguageCommon> {
9    let language = tree_sitter_rust::LANGUAGE.into();
10    let validation_query = Some(tree_sitter::Query::new(
11        &language,
12        include_str!("../../queries/rust/validation.scm"),
13    )?);
14    let editor = Box::new(RustEditor);
15
16    Ok(LanguageCommon {
17        language,
18        validation_query,
19        editor,
20        name: LanguageName::Rust,
21        file_extensions: &["rs"],
22    })
23}
24
25struct RustEditor;
26
27impl LanguageEditor for RustEditor {
28    fn format_code(&self, source: &str) -> Result<String> {
29        let mut child = Command::new("rustfmt")
30            .args(["--emit", "stdout", "--edition", "2024"])
31            .stdin(Stdio::piped())
32            .stdout(Stdio::piped())
33            .stderr(Stdio::piped())
34            .spawn()?;
35
36        if let Some(mut stdin) = child.stdin.take() {
37            stdin.write_all(source.as_bytes())?;
38            drop(stdin);
39        }
40
41        let mut stdout = String::new();
42        if let Some(mut out) = child.stdout.take() {
43            out.read_to_string(&mut stdout)?;
44        }
45
46        let mut stderr = String::new();
47        if let Some(mut err) = child.stderr.take() {
48            err.read_to_string(&mut stderr)?;
49        }
50
51        if child.wait()?.success() {
52            Ok(stdout)
53        } else {
54            Err(anyhow!(stderr))
55        }
56    }
57}