rust-diagnostics

This is a utility to insert XML markups to the code fragments that causing diagnostic error or warning in Rust. Rust compiler produces many diagnostic information to the console, using file name and line numbers to indicate the exact location. However, that requires a programmer to go back and forth between the command console and an editor. This utility would make it easier to insert the diagnostic messages in place, similar to the idea of 'in-place' editing concept.

Moreover, the diagnostic information added into the code sequence could enable further transformer-based machine learning approaches to analyse the semantics of Rust programas.

Currently we integrate it with rust-clippy, but it could also work for cargo-build commands.

The format of the marked up code would look like the following:

```rust use cargometadata::Message; use std::{ collections::HashMap, fs::readto_string, path::PathBuf, process::{Command, Stdio}, };

[derive(Debug, Clone)]

struct Ran { name: String, start: usize, end: usize, note: String, }

// insert diagnostic code as an markup element around the code causing the diagnostic message fn markup(source: &[u8], map: Vec) -> Vec { let mut output = Vec::new(); for (i, c) in source.iter().enumerate() { let found = false; for m in &map { // deal with the element if m.start <= i && i < m.end && i == m.start { output.extend(format!("<{}>", m.name).asbytes()); } if m.end == i { match m.note.asstr() { "None" => output.extend(format!("bytes()), _ => output.extend(format!("

// Run cargo clippy to generate warnings from "foo.rs" into temporary "foo.rs.1" files fn main() { removepreviouslygeneratedfiles(); let mut command = Command::new("cargo") // .args(["build", "--message-format=json"]) .args(["clippy", "--message-format=json"]) .stdout(Stdio::piped()) .spawn() .unwrap(); let reader = std::io::BufReader::new(command.stdout.take().unwrap()); let mut map = HashMap::new(); for message in cargometadata::Message::parsestream(reader) { if let Message::CompilerMessage(msg) = message.unwrap() { <#[Warning(clippy::dbgmacro)>dbg!(&msg)

&msg]]; let nm = msg .message .children .intoiter() .map(|x| { let ss = x .spans .iter() .filter(|y| { y.suggestedreplacement.issome() && !&y .suggestedreplacement .asref() .unwrap() .asstr() .isempty() }) .filter(|x| { x.suggestedreplacement.issome() && !x.suggestedreplacement.asref().unwrap().isempty() }) .map(|x| x.suggestedreplacement.asref().unwrap().asstr()) .collect::>() .join("\n"); ss }) .collect::>() .join("\n"); for s in msg.message.spans { let x = <#[Warning(clippy::asconversions)>s.bytestart as usizeconversions)>[[

]]; let y = <#[Warning(clippy::asconversions)>s.byteend as usizeconversions)>[[ ]]; let r = Ran { // name: msg.message.message.clone(), name: format!( "#[{:?}({})", msg.message.level, msg.message.code.clone().unwrap().code ), start: x, end: y, note: <#[Warning(clippy::uselessformat)>format!("{}", &nm)

(&nm).tostring()]], }; let filename = s.filename; <#[Warning(clippy::mapentry)>if !map.containskey(&filename) { let v = vec![r]; map.insert(filename, v); } else { let v = map.getmut(&filename).unwrap(); v.push(r); }entry)>[[

if let std::collections::hashmap::Entry::Vacant(e) = map.entry(filename) { let v = vec![r]; e.insert(v); } else { let v = map.getmut(&filename).unwrap(); v.push(r); }]] } } } for file in map.keys() { let source = readtostring(file).ok().unwrap(); let v = map.get(file).unwrap(); let output = markup(source.asbytes(), v.tovec()); let path = PathBuf::from(file); let filename = path.parent().unwrap().join(format!( "{}.rs.1", path.filestem().unwrap().tostringlossy() )); println!("Marked warning(s) into {:?}", &filename); if !filename.parent().unwrap().exists() { std::fs::createdir(filename.parent().unwrap()).ok(); } std::fs::write(&filename, std::str::fromutf8(&output).unwrap()).ok(); } let _output = command.wait().expect("Couldn't get cargo's exit status"); }

fn removepreviouslygeneratedfiles() { let command = Command::new("find") .args([".", "-name", "*.rs.1"]) .stdout(Stdio::piped()) .spawn() .unwrap(); let output = command .waitwithoutput() .expect("failed to aquire programm output") .stdout; if !output.isempty() { println!("Removed previously generated warning files") } String::fromutf8(output) .expect("programm output was not valid utf-8") .split('\n') .foreach(|tmp| { let mut command = Command::new("rm") .args(["-f", tmp]) .stdout(Stdio::piped()) .spawn() .unwrap(); command.wait().expect("problem with file deletion"); }); } ```

Note that this is a result applying the rust-diagnostic utilility on its own implementation, i.e., eating our own dog food :-)

Update

Acknowledgement