semantic_code_edit_mcp/languages/
rust.rs1use 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}