1#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)]
10#![recursion_limit = "512"]
11
12extern crate core;
13extern crate proc_macro;
14extern crate proc_macro2;
15#[macro_use]
16extern crate quote;
17extern crate syn;
18
19use class::{parse_class, ClassAttr};
20use class_impl::{parse_impl, ImplAttr};
21use proc_macro::Diagnostic;
22use proc_macro2::{Span, TokenStream};
23use protocol::{parse_protocol, ProtocolAttr};
24use quote::quote;
25use syn::parse2;
26use syn::parse::{ParseStream, Parse};
27
28mod class;
29mod class_impl;
30mod gensym;
31mod ivar;
32mod property;
33mod protocol;
34mod selector;
35mod test;
36mod util;
37
38enum ObjrsAttr {
39 Impl(ImplAttr),
40 Class(ClassAttr),
41 Protocol(ProtocolAttr),
42 Selector(Span),
43 Ivar(Span),
44}
45
46impl Parse for ObjrsAttr {
47 fn parse(input: ParseStream) -> syn::parse::Result<Self> {
48 use syn::token::Impl;
49 use util::{ivar, selector, class, protocol};
50
51 let lookahead = input.lookahead1();
52 if lookahead.peek(Impl) {
53 return input.parse().map(ObjrsAttr::Impl);
54 } else if lookahead.peek(class) {
55 return input.parse().map(ObjrsAttr::Class);
56 } else if lookahead.peek(protocol) {
57 return input.parse().map(ObjrsAttr::Protocol);
58 } else if lookahead.peek(selector) {
59 return Ok(ObjrsAttr::Selector(input.cursor().span()));
60 } else if lookahead.peek(ivar) {
61 return Ok(ObjrsAttr::Ivar(input.cursor().span()));
62 }
63 return Err(lookahead.error());
64 }
65}
66
67fn to_diagnostic(err: syn::parse::Error) -> Diagnostic {
68 return err.span().unstable().error(err.to_string());
69}
70
71fn shim(args: TokenStream, input: TokenStream) -> Result<TokenStream, Diagnostic> {
72 match parse2(args).map_err(to_diagnostic)? {
73 ObjrsAttr::Impl(attr) => return parse_impl(attr, input),
74 ObjrsAttr::Class(attr) => return parse_class(attr, input),
75 ObjrsAttr::Protocol(attr) => return parse_protocol(attr, input),
76 ObjrsAttr::Selector(span) => {
77 return Err(
78 span
79 .unstable()
80 .error("attribute must be enclosed in an impl block with a #[objrs(impl)] attribute"),
81 )
82 }
83 ObjrsAttr::Ivar(span) => {
84 return Err(
85 span
86 .unstable()
87 .error("attribute must be enclosed in a struct item with a #[objrs(class)] attribute"),
88 )
89 }
90 }
91}
92
93#[proc_macro_attribute]
94pub fn objrs(
95 args: proc_macro::TokenStream,
96 input: proc_macro::TokenStream,
97) -> proc_macro::TokenStream {
98 match shim(args.into(), input.into()) {
99 Ok(stream) => return stream.into(),
100 Err(diagnostic) => {
101 diagnostic.emit();
102 return proc_macro::TokenStream::new();
103 }
104 }
105}
106
107#[proc_macro]
108pub fn selector(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
109 match selector::parse_selector_ref(input.into()) {
110 Ok(stream) => return stream.into(),
111 Err(diagnostic) => {
112 diagnostic.emit();
113 return quote!{{
115 extern crate objrs as __objrs_root;
116 __objrs_root::runtime::SEL(0 as *const _)
117 }}.into();
118 }
119 }
120}
121
122