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
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// dirmod
// Copyright (C) SOFe
//
// Licensed under the Apache License, Version 2.0 (the License);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an AS IS BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![feature(proc_macro_span)]

extern crate proc_macro;

macro_rules! decl {
    ($name:ident: $(#[$docs:meta])*) => {
        #[proc_macro]
        $(#[$docs])*
        pub fn $name(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
            match imp::$name(ts.into()) {
                Ok(ts) => ts,
                Err(err) => err.to_compile_error(),
            }.into()
        }
    };
}

decl!(all:
      /// Include all possible modules in the directory
      ///
      /// # Parameters
      /// The following parameter statements can be joined by semicolons.
      /// - `default $vis [use]`: All modules have `$vis` visibility by default,
      ///   where `$vis` can be the standard visibilities like `pub`, `pub(crate)`,
      ///   etc. The special `priv` keyword can be used to indicate private
      ///   visibility. If the `use` keyword is added behind the visibility,
      ///   modules will remain private, and `$vis use module::*;` statements
      ///   would be appended.
      ///   If this statement is not given, `priv` is assumed for default.
      /// - `$vis [use] $name1, $name2, ...`: The specified modules have `$vis`
      ///   visibility, different from the default visibility.
      ///   The format of `$vis [use]` is identical to that in `default`.
      /// - `except $name1 $name2 ...`: The specified modules are excluded.
      ///
      /// For simplicity, there is no special syntax to add doc comments.
      /// To document modules, either use the `//!` inner documentation
      /// syntax within the module file, or use `except` to exclude
      /// declaration and declare them separately from the macro call.
      ///
      /// # Examples
      /// ```ignore
      /// all!();
      /// ```
      ///
      /// ```ignore
      /// all!(default pub(crate); pub foo);
      /// ```
      ///
      /// ```ignore
      /// all! {
      ///     default pub(super);
      ///     pub(crate) foo, bar;
      ///     pub qux, corge;
      ///     priv lorem;
      ///     except ipsum;
      /// }
      /// ```
      );

decl!(os:
      /// Includes modules based on the `target_os` cfg attribute.
      ///
      /// Each module named `$mod` is conditionally compiled with the
      /// `#[cfg(target_os = $mod)]` option, allowing OS-specific module
      /// files/directories like `windows.rs`, `unix.rs`, etc.
      ///
      /// Note that this macro does not check for nonexistent `target_os`
      /// values, so incorrect usage will not lead to any warnings
      /// (and likely never compile the incorrect modules).
      /// See [this page](https://doc.rust-lang.org/reference/conditional-compilation.html)
      /// for a list of possible values.
      ///
      /// It is usually a good idea to provide the `use` keyword and expose
      /// the same API methods in all specific operating systems, preventing
      /// the need of `target_os` checking outside the crate.
      ///
      /// # Parameters
      /// ```ignore
      /// os!($vis [use] [|| [$error]]);
      /// ```
      ///
      /// `os!` accepts a visibility and an optional `use` keyword, with the
      /// same meaning as those in [`all!`](macro.all.html).
      ///
      /// The optional `|| $error` clause adds the code to check if at least
      /// one of the modules is compiled; otherwise,
      /// [`compile_error!`](https://doc.rust-lang.org/std/macro.compile_error.html)
      /// would be triggered. `$error` should be a string literal. If `$error`
      /// is omitted, it is replaced by the default message
      /// `"target_os must be one of \"xxx\", \"yyy\", ..."`,
      /// where xxx and yyy are the available modules.
      ///
      /// `os!` does not provide any filtering, and is intended for parent
      /// modules with only platform-specific submodules.  If non-OS-specific
      /// modules are desired, consider moving the OS-specific modules to the
      /// same directory.
      ///
      /// # Examples
      /// ```ignore
      /// os!(priv ||);
      /// ```
      ///
      /// ```ignore
      /// os!(pub use || "Unsupported operating system");
      /// ```
      ///
      /// If none of the modules in the directory get compiled, compilation
      /// would abort with the message "Unsupported operating system".
      );

decl!(family:
      /// Includes modules based on the `target_family` cfg attribute.
      ///
      /// This macro is identical to [`os!`](macro.os.html), except `target_os`
      /// is replaced with `target_family`, hence only accepting
      /// `windows.rs` and `unix.rs`.
      ///
      /// However, similar to `os!`, this macro does not validate values.
      /// Use the `||` syntax to report errors correctly.
      );

decl!(feature:
      /// Includes modules based on the `feature` cfg attribute.
      ///
      /// This macro has exactly the same semantics and format as
      /// [`os!`](macro.os.html) except it uses `#[cfg(feature = $module)]`
      /// instead of `target_os`.
      ///
      /// # Parameters
      /// ```ignore
      /// feature!($vis [use] [|| [$error]]);
      /// ```
      ///
      /// See [`os!](macro.os.html) for explanation of the parameter values.
      );

mod imp;
mod parse;