1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//! Provides function to deal with Rust syntax.
#![deny(warnings)]
#![warn(missing_docs)]

mod near_syn;
pub mod ts;

pub use crate::near_syn::*;

use std::{
    fs::File,
    io::{Read, Write},
    path::Path,
};
use syn::{Attribute, Lit, Meta, MetaNameValue};

/// Defines the `Args` to be used in binaries.
#[macro_export]
macro_rules! Args {
    ($bin_name:expr) => {
        #[derive(clap::Clap)]
        #[clap(name = $bin_name, version = env!("CARGO_PKG_VERSION"), author = env!("CARGO_PKG_AUTHORS"))]
        #[clap(setting = clap::AppSettings::ColoredHelp)]
        struct Args {

            /// Does not emit date/time information,
            /// otherwise current time is being emitted
            #[clap(long)]
            no_now: bool,

            #[clap()]
            files: Vec<String>,

            #[clap(skip)]
            now: Option<String>,
        }
        impl Args {
            fn now(&mut self) -> String {
                if self.now.is_none() {
                    self.now = Some(if self.no_now {"".to_string()} else {format!("on {}",chrono::Utc::now().to_string())});
                }
                self.now.clone().unwrap()
            }
        }
    }
}

/// Returns the Rust syntax tree for the given `file_name` path.
/// Panics if the file cannot be open or the file has syntax errors.
pub fn parse_rust<S: AsRef<Path>>(file_name: S) -> syn::File {
    let mut file = File::open(file_name).expect("Unable to open file");
    let mut src = String::new();
    file.read_to_string(&mut src).expect("Unable to read file");

    syn::parse_file(&src).expect("Unable to parse file")
}

/// Joins segments of path by `::`.
pub fn join_path(path: &syn::Path) -> String {
    path.segments
        .iter()
        .map(|seg| seg.ident.to_string())
        .collect::<Vec<String>>()
        .join("::")
}

/// Writes Rust `doc` comments to `file`.
/// Each line of `doc` is prefixed with `prefix`.
pub fn write_docs<W: Write, F: Fn(String) -> String>(
    file: &mut W,
    attrs: &Vec<Attribute>,
    mapf: F,
) {
    for attr in attrs {
        if attr.path.is_ident("doc") {
            if let Ok(Meta::NameValue(MetaNameValue {
                lit: Lit::Str(lit), ..
            })) = attr.parse_meta()
            {
                writeln!(file, "{}", mapf(lit.value())).unwrap();
            } else {
                panic!("not expected");
            }
        }
    }
}