bok/bok-macro/src/lib.rs
Luca Fulchir 87b83371e8
tiny cleanup
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
2024-12-11 20:53:27 +01:00

348 lines
9.5 KiB
Rust

/*
* Copyright 2024 Luca Fulchir <luca.fulchir@runesauth.com>
*
* Licensed under the Apache License, Version 2.0 with LLVM exception (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License and of the exception at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://spdx.org/licenses/LLVM-exception.html
*
* 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)]
use ::proc_macro::TokenStream;
mod collection;
mod pkgs;
mod repos;
//
// ####### Repository stuff ##########
//
/// Use as #[::bok::repository(MyBaseRepo)]
/// Will setup a `base` field that is the given base repo
/// and add `#[derive(::bok::Repository)]`
///
/// e.g.: `#[::bok::repository(::bok::RepositoryEmpty)]`
#[::macro_magic::import_tokens_attr]
//#[with_custom_parsing(repos::BaseSet)]
#[proc_macro_attribute]
pub fn repository(attrs: TokenStream, input: TokenStream) -> TokenStream {
crate::repos::repository(attrs, input)
}
/// Unless you know what you are doing, use `#[::bok::repository(MyBaseRepo)]`
/// instead needs a `.base` field
///
/// Use like:
/// ```
/// #[derive(::bok::Repository)]
/// pub struct MyRepo {
/// base : BaseRepo,
/// }
/// ```
/// adds extension capabilities to a repo
#[proc_macro_derive(Repository)]
pub fn derive_repository(input: TokenStream) -> TokenStream {
crate::repos::derive_repository(input)
}
/// Add multiple packages to a repo
/// Usage:
/// ```
/// #[::bok::repo_packages(Mypkg1, Mypkg2)]
/// struct MyRepo{}
/// ```
#[proc_macro_attribute]
pub fn repo_packages(attrs: TokenStream, input: TokenStream) -> TokenStream {
crate::repos::repo_packages(attrs, input)
}
/// Create the methods that will return the builders and packages
///
/// will actually merely rewrite the macro to get the actual Repo name
/// in `#[::bok_macro::repo_impl_methods(MyRepo)]`
///
/// Usage:
/// ```
/// #[::bok::repo_impl]
/// impl MyRepo{}
/// ```
//#[::macro_magic::import_tokens_attr]
#[proc_macro_attribute]
pub fn repo_impl(attrs: TokenStream, input: TokenStream) -> TokenStream {
crate::repos::repo_impl(attrs, input)
}
/// **Internal. Do not use unless you know what you are doing**
/// Create the methods that will return the builders and packages
/// Usage:
/// ```
/// #[::bok_macro::repo_impl_methods(MyRepo)]
/// impl MyRepo{}
/// ```
#[::macro_magic::import_tokens_attr]
#[proc_macro_attribute]
pub fn repo_impl_methods(
attrs: TokenStream,
input: TokenStream,
) -> TokenStream {
crate::repos::repo_impl_methods(attrs, input, __source_path)
}
/// **Internal. Do not use unless you know what you are doing**
/// given a Repository and a trait "BokDeps...",
/// implement all the fn returning the dependencies needed by the package
///
/// Usage:
/// ```
/// #[::bok_macro::repo_impl_(MyRepo)]
/// impl MyRepo{}
/// ```
#[::macro_magic::import_tokens_attr]
#[proc_macro_attribute]
pub fn repo_impl_pkg_deps(
attrs: TokenStream,
input: TokenStream,
) -> TokenStream {
crate::repos::repo_impl_pkg_deps(attrs, input)
}
/// **Internal**
///
/// add implementation of a collection
#[proc_macro_attribute]
pub fn collection(attrs: TokenStream, input: TokenStream) -> TokenStream {
crate::collection::collection(attrs, input)
}
/// **Internal**
///
/// add implementation of a `BokBuilderDeps` trait
#[::macro_magic::import_tokens_attr]
#[proc_macro_attribute]
pub fn collection_dep(attrs: TokenStream, input: TokenStream) -> TokenStream {
crate::collection::collection_dep(attrs, input, __source_path)
}
//
// ####### Package stuff ##########
//
/// Use on a function as `#[::bok::pkg_fn_to_code]`
/// will create a new function, same name with `_code` that
/// returns the ::proc_macro2::TokenStream of the function
///
/// **Don't use this if you are using `#[::bok::package(...)]`
/// it is already automatically added to all members of trait `::bok::Pkg`**
///
/// e.g.:
/// ```
/// impl MyPackage {
/// #[::bok::pkg_fn_to_code]
/// fn build() {
/// ...
/// }
/// }
/// let p = MyPackage::default();
/// let tokens : ::proc_macro2::TokenStream = p.build_code()
/// ```
#[proc_macro_attribute]
pub fn pkg_fn_to_code(attrs: TokenStream, input: TokenStream) -> TokenStream {
crate::pkgs::pkg_fn_to_code(attrs, input)
}
/// Use as #[::bok::package(MyBasePackage)]
/// Will setup a `base` field that is the given base package
/// and add `#[derive(::bok::Package)]`
///
/// e.g.:
/// ```
/// #[::bok::package(::bok::PkgEmpty)]
/// pub struct MyPkg {}
/// ```
#[proc_macro_attribute]
pub fn package(attrs: TokenStream, input: TokenStream) -> TokenStream {
crate::pkgs::package(attrs, input)
}
/// **Internal**. try not to use
/// Use as #[::bok::package(MyBasePackage<R>)]
/// Will setup a `base` field that is the given base package
/// and add `#[derive(::bok::Package)]`
/// needs generics
///
/// e.g.:
/// ```
/// #[::bok::package_path(::base::pkg<R>)]
/// pub struct MyPkg {}
/// ```
#[::macro_magic::import_tokens_attr]
#[proc_macro_attribute]
pub fn package_path(attrs: TokenStream, input: TokenStream) -> TokenStream {
crate::pkgs::package_path(attrs, input, __source_path)
}
/// Specify one or more dependencies
///
/// e.g:
/// ```
/// #[::bok::package(::bok::PkgEmpty)]
/// #[::bok::deps(some::Package, other::Package)]
/// pub struct MyPkg {}
/// ```
#[proc_macro_attribute]
pub fn deps(attrs: TokenStream, input: TokenStream) -> TokenStream {
crate::pkgs::deps(attrs, input)
}
/*
/// attribute for package optional feature fields
/// marks a struct field as a package option
/// the PkgBuilder will create apposite get/set and traits for the options
///
/// e.g:
/// ```
/// #[::bok::package(::bok::PkgEmpty)]
/// pub struct MyPkg {
/// #[::bok::option]
/// with_ssl: bool,
/// }
/// ```
#[proc_macro_attribute]
pub fn option(attrs: TokenStream, input: TokenStream) -> TokenStream {
crate::pkgs::option(attrs, input)
}
*/
/// Use as #[::bok::package_impl]
/// adds the right generics to the package.
///
/// extra calls and changes are added to `::bok::Pkg` and ::std::Default traits
///
/// e.g.:
/// ```
/// #[::bok::package_impl]
/// impl Default for Mypackage {
/// fn default() -> Self { ... }
/// }
/// #[::bok::package_impl]
/// impl ::bok::Pkg for MyPackage {
/// fn build(&self) -> Result<(),()> {
/// ...
/// }
/// }
/// ```
#[proc_macro_attribute]
pub fn package_impl(attrs: TokenStream, input: TokenStream) -> TokenStream {
crate::pkgs::package_impl(attrs, input)
}
/// ** Internal, don't use unless you know what you are doing.**
/// Use as #[::bok::package_impl_base(::my::Package)]
/// implements common ::bok::Pkg methods and takes the package methods
/// not implemented by the user from the base package
///
/// does not export symbols.
///
/// should be called with the same path as the package that implements
/// ::bok::Pkg
///
/// will rewrite itself with the exported impl path of the base package
/// so that macro_magic can import the base impl
///
/// e.g.:
/// ```
/// #[::bok::package_impl_base(MyPackage)]
/// #[::macro_magic::export_tokens(_bok_pkg_mypackage)]
/// impl ::bok::Pkg for MyPackage {
/// fn build(&self) -> Result<(),()> {
/// ...
/// }
/// }
/// ```
#[::macro_magic::import_tokens_attr]
#[proc_macro_attribute]
pub fn package_impl_base(
attrs: TokenStream,
input: TokenStream,
) -> TokenStream {
crate::pkgs::package_impl_base(attrs, input)
}
/// ** Internal, don't use unless you know what you are doing.**
/// Use as #[::bok::package_impl_builder(::my::Package)]
/// implements common ::bok::PkgBuilder methods and takes
/// the package methods not implemented by the user from the base package
///
/// does not export symbols.
///
/// should be called with the same path as the package that implements
/// ::bok::Pkg
///
/// will rewrite itself with the exported impl path of the base package
/// so that macro_magic can import the base impl
///
/// e.g.:
/// ```
/// #[::bok::package_impl_builder(MyPackage)]
/// #[::macro_magic::export_tokens(_bok_pkgbuilder_mypackage)]
/// impl ::bok::PkgBuilder for MyPackage {
/// fn set_dependencies(&self, ...) -> Result<(),()> {
/// ...
/// }
/// }
/// ```
#[::macro_magic::import_tokens_attr]
#[proc_macro_attribute]
pub fn package_impl_builder(
attrs: TokenStream,
input: TokenStream,
) -> TokenStream {
crate::pkgs::package_impl_builder(attrs, input, __source_path)
}
/// Unless you know what you are doing, use `#[::bok::package(MyBasePackage)]`
/// instead needs a `.base` field
///
/// ```
/// #[derive(::bok::Package)]
/// pub struct MyPkg {
/// base: OtherPkg
/// }
/// ```
/// adds:
/// * Builder pattern to a package
/// * getters/setters for all package fields
/// * deref for package
#[proc_macro_derive(Package, attributes(option))]
pub fn derive_package(input: TokenStream) -> TokenStream {
crate::pkgs::derive_package(input)
}
// ==== Common package stuff ====
pub(crate) struct PathList(Vec<::syn::Path>);
impl ::syn::parse::Parse for PathList {
fn parse(input: ::syn::parse::ParseStream) -> syn::Result<Self> {
use ::syn::punctuated::Punctuated;
let raw =
Punctuated::<::syn::Path, ::syn::Token![,]>::parse_terminated(
input,
)?;
let mut result = Vec::with_capacity(raw.len());
for r in raw.into_iter() {
result.push(r)
}
Ok(PathList(result))
}
}