dirmod_codegen/lib.rs
1// dirmod
2// Copyright (C) SOFe
3//
4// Licensed under the Apache License, Version 2.0 (the License);
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an AS IS BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16#![feature(proc_macro_span)]
17
18extern crate proc_macro;
19
20macro_rules! decl {
21 ($name:ident: $(#[$docs:meta])*) => {
22 #[proc_macro]
23 $(#[$docs])*
24 pub fn $name(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
25 match imp::$name(ts.into()) {
26 Ok(ts) => ts,
27 Err(err) => err.to_compile_error(),
28 }.into()
29 }
30 };
31}
32
33decl!(all:
34 /// Include all possible modules in the directory
35 ///
36 /// # Parameters
37 /// The following parameter statements can be joined by semicolons.
38 /// - `default $vis [use]`: All modules have `$vis` visibility by default,
39 /// where `$vis` can be the standard visibilities like `pub`, `pub(crate)`,
40 /// etc. The special `priv` keyword can be used to indicate private
41 /// visibility. If the `use` keyword is added behind the visibility,
42 /// modules will remain private, and `$vis use module::*;` statements
43 /// would be appended.
44 /// If this statement is not given, `priv` is assumed for default.
45 /// - `$vis [use] $name1, $name2, ...`: The specified modules have `$vis`
46 /// visibility, different from the default visibility.
47 /// The format of `$vis [use]` is identical to that in `default`.
48 /// - `except $name1 $name2 ...`: The specified modules are excluded.
49 ///
50 /// For simplicity, there is no special syntax to add doc comments.
51 /// To document modules, either use the `//!` inner documentation
52 /// syntax within the module file, or use `except` to exclude
53 /// declaration and declare them separately from the macro call.
54 ///
55 /// # Examples
56 /// ```ignore
57 /// all!();
58 /// ```
59 ///
60 /// ```ignore
61 /// all!(default pub(crate); pub foo);
62 /// ```
63 ///
64 /// ```ignore
65 /// all! {
66 /// default pub(super);
67 /// pub(crate) foo, bar;
68 /// pub qux, corge;
69 /// priv lorem;
70 /// except ipsum;
71 /// }
72 /// ```
73 );
74
75decl!(os:
76 /// Includes modules based on the `target_os` cfg attribute.
77 ///
78 /// Each module named `$mod` is conditionally compiled with the
79 /// `#[cfg(target_os = $mod)]` option, allowing OS-specific module
80 /// files/directories like `windows.rs`, `unix.rs`, etc.
81 ///
82 /// Note that this macro does not check for nonexistent `target_os`
83 /// values, so incorrect usage will not lead to any warnings
84 /// (and likely never compile the incorrect modules).
85 /// See [this page](https://doc.rust-lang.org/reference/conditional-compilation.html)
86 /// for a list of possible values.
87 ///
88 /// It is usually a good idea to provide the `use` keyword and expose
89 /// the same API methods in all specific operating systems, preventing
90 /// the need of `target_os` checking outside the crate.
91 ///
92 /// # Parameters
93 /// ```ignore
94 /// os!($vis [use] [|| [$error]]);
95 /// ```
96 ///
97 /// `os!` accepts a visibility and an optional `use` keyword, with the
98 /// same meaning as those in [`all!`](macro.all.html).
99 ///
100 /// The optional `|| $error` clause adds the code to check if at least
101 /// one of the modules is compiled; otherwise,
102 /// [`compile_error!`](https://doc.rust-lang.org/std/macro.compile_error.html)
103 /// would be triggered. `$error` should be a string literal. If `$error`
104 /// is omitted, it is replaced by the default message
105 /// `"target_os must be one of \"xxx\", \"yyy\", ..."`,
106 /// where xxx and yyy are the available modules.
107 ///
108 /// `os!` does not provide any filtering, and is intended for parent
109 /// modules with only platform-specific submodules. If non-OS-specific
110 /// modules are desired, consider moving the OS-specific modules to the
111 /// same directory.
112 ///
113 /// # Examples
114 /// ```ignore
115 /// os!(priv ||);
116 /// ```
117 ///
118 /// ```ignore
119 /// os!(pub use || "Unsupported operating system");
120 /// ```
121 ///
122 /// If none of the modules in the directory get compiled, compilation
123 /// would abort with the message "Unsupported operating system".
124 );
125
126decl!(family:
127 /// Includes modules based on the `target_family` cfg attribute.
128 ///
129 /// This macro is identical to [`os!`](macro.os.html), except `target_os`
130 /// is replaced with `target_family`, hence only accepting
131 /// `windows.rs` and `unix.rs`.
132 ///
133 /// However, similar to `os!`, this macro does not validate values.
134 /// Use the `||` syntax to report errors correctly.
135 );
136
137decl!(feature:
138 /// Includes modules based on the `feature` cfg attribute.
139 ///
140 /// This macro has exactly the same semantics and format as
141 /// [`os!`](macro.os.html) except it uses `#[cfg(feature = $module)]`
142 /// instead of `target_os`.
143 ///
144 /// # Parameters
145 /// ```ignore
146 /// feature!($vis [use] [|| [$error]]);
147 /// ```
148 ///
149 /// See [`os!](macro.os.html) for explanation of the parameter values.
150 );
151
152mod imp;
153mod parse;