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
87
88
89
#![feature(plugin_registrar, rustc_private, type_ascription)]
extern crate rustc_plugin;
extern crate syntax;
use rustc_plugin::registry::Registry;
use syntax::ast::Name;
use syntax::ext::base::{ AttrProcMacro, ExtCtxt, SyntaxExtension };
use syntax::codemap::Span;
use syntax::tokenstream::TokenStream;
use syntax::tokenstream::TokenTree;
use syntax::parse::token::{ Lit, Token };
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;
#[plugin_registrar]
pub fn registrar(reg: &mut Registry) {
reg.register_syntax_extension( Name::intern("rdoc"),
SyntaxExtension::AttrProcMacro(
Box::new(Expansion)
)
);
}
struct Expansion;
impl AttrProcMacro for Expansion {
fn expand<'cx>(&self,
_: &'cx mut ExtCtxt,
_: Span,
annotation: TokenStream,
annotated: TokenStream) -> TokenStream
{
if !annotation.is_empty() {
let mut trees = annotation.into_trees();
if let Some(TokenTree::Token(_, val)) = trees.next() {
if val == Token::Eq {
if let Some(TokenTree::Token(_, val)) = trees.next() {
if let Token::Literal(Lit::Str_(path) ,_) = val {
let out = TokenStream::concat(
vec![
TokenStream::from(
Token::DocComment(
Name::intern(
&docs_gen(&path.as_str())
)
)
)
, annotated
]
);
out
} else {
annotated
}
} else {
annotated
}
} else {
annotated
}
} else {
annotated
}
} else {
annotated
}
}
}
fn docs_gen(path: &str) -> String {
let mut buf_reader = BufReader::new( File::open(path)
.expect(
&format!("Failed to open {} \
while expanding out \
documentation", path)
)
);
let mut comments = String::new() + "///";
let _ = buf_reader.read_to_string(&mut comments);
comments
}