Simplify codegen.
This commit is contained in:
parent
363085efc3
commit
809b813def
@ -3,7 +3,7 @@ use syn::{
|
|||||||
spanned::Spanned,
|
spanned::Spanned,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum ExportScope {
|
pub enum ExportScope {
|
||||||
PubOnly,
|
PubOnly,
|
||||||
Prefix(String),
|
Prefix(String),
|
||||||
@ -22,12 +22,14 @@ pub trait ExportedParams: Sized {
|
|||||||
fn from_info(info: ExportInfo) -> syn::Result<Self>;
|
fn from_info(info: ExportInfo) -> syn::Result<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct AttrItem {
|
pub struct AttrItem {
|
||||||
pub key: proc_macro2::Ident,
|
pub key: proc_macro2::Ident,
|
||||||
pub value: Option<syn::LitStr>,
|
pub value: Option<syn::LitStr>,
|
||||||
pub span: proc_macro2::Span,
|
pub span: proc_macro2::Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct ExportInfo {
|
pub struct ExportInfo {
|
||||||
pub item_span: proc_macro2::Span,
|
pub item_span: proc_macro2::Span,
|
||||||
pub items: Vec<AttrItem>,
|
pub items: Vec<AttrItem>,
|
||||||
|
@ -22,23 +22,30 @@ use crate::attrs::{ExportInfo, ExportScope, ExportedParams};
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Copy, Hash)]
|
#[derive(Clone, Debug, Eq, PartialEq, Copy, Hash)]
|
||||||
pub enum FnNamespaceAccess {
|
pub enum FnNamespaceAccess {
|
||||||
|
Unset,
|
||||||
Global,
|
Global,
|
||||||
Internal,
|
Internal,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
impl Default for FnNamespaceAccess {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Unset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, Copy, Hash)]
|
||||||
pub enum Index {
|
pub enum Index {
|
||||||
Get,
|
Get,
|
||||||
Set,
|
Set,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
pub enum Property {
|
pub enum Property {
|
||||||
Get(syn::Ident),
|
Get(syn::Ident),
|
||||||
Set(syn::Ident),
|
Set(syn::Ident),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
pub enum FnSpecialAccess {
|
pub enum FnSpecialAccess {
|
||||||
None,
|
None,
|
||||||
Index(Index),
|
Index(Index),
|
||||||
@ -101,7 +108,7 @@ pub(crate) struct ExportedFnParams {
|
|||||||
pub return_raw: bool,
|
pub return_raw: bool,
|
||||||
pub skip: bool,
|
pub skip: bool,
|
||||||
pub special: FnSpecialAccess,
|
pub special: FnSpecialAccess,
|
||||||
pub namespace: Option<FnNamespaceAccess>,
|
pub namespace: FnNamespaceAccess,
|
||||||
pub span: Option<proc_macro2::Span>,
|
pub span: Option<proc_macro2::Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +145,7 @@ impl ExportedParams for ExportedFnParams {
|
|||||||
let mut name = Vec::new();
|
let mut name = Vec::new();
|
||||||
let mut return_raw = false;
|
let mut return_raw = false;
|
||||||
let mut skip = false;
|
let mut skip = false;
|
||||||
let mut namespace = None;
|
let mut namespace = FnNamespaceAccess::Unset;
|
||||||
let mut special = FnSpecialAccess::None;
|
let mut special = FnSpecialAccess::None;
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
let crate::attrs::AttrItem {
|
let crate::attrs::AttrItem {
|
||||||
@ -226,22 +233,16 @@ impl ExportedParams for ExportedFnParams {
|
|||||||
("global", Some(s)) | ("internal", Some(s)) => {
|
("global", Some(s)) | ("internal", Some(s)) => {
|
||||||
return Err(syn::Error::new(s.span(), "extraneous value"))
|
return Err(syn::Error::new(s.span(), "extraneous value"))
|
||||||
}
|
}
|
||||||
("global", None) => {
|
("global", None) => match namespace {
|
||||||
if let Some(ns) = namespace {
|
FnNamespaceAccess::Unset => namespace = FnNamespaceAccess::Global,
|
||||||
if ns != FnNamespaceAccess::Global {
|
FnNamespaceAccess::Global => (),
|
||||||
return Err(syn::Error::new(key.span(), "conflicting namespace"));
|
_ => return Err(syn::Error::new(key.span(), "conflicting namespace")),
|
||||||
}
|
},
|
||||||
}
|
("internal", None) => match namespace {
|
||||||
namespace = Some(FnNamespaceAccess::Global);
|
FnNamespaceAccess::Unset => namespace = FnNamespaceAccess::Internal,
|
||||||
}
|
FnNamespaceAccess::Internal => (),
|
||||||
("internal", None) => {
|
_ => return Err(syn::Error::new(key.span(), "conflicting namespace")),
|
||||||
if let Some(ns) = namespace {
|
},
|
||||||
if ns != FnNamespaceAccess::Internal {
|
|
||||||
return Err(syn::Error::new(key.span(), "conflicting namespace"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
namespace = Some(FnNamespaceAccess::Internal);
|
|
||||||
}
|
|
||||||
(attr, _) => {
|
(attr, _) => {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
key.span(),
|
key.span(),
|
||||||
|
@ -19,9 +19,9 @@ use std::borrow::Cow;
|
|||||||
use crate::attrs::{AttrItem, ExportInfo, ExportScope, ExportedParams};
|
use crate::attrs::{AttrItem, ExportInfo, ExportScope, ExportedParams};
|
||||||
use crate::function::ExportedFnParams;
|
use crate::function::ExportedFnParams;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash, Default)]
|
||||||
pub(crate) struct ExportedModParams {
|
pub(crate) struct ExportedModParams {
|
||||||
pub name: Option<String>,
|
pub name: String,
|
||||||
skip: bool,
|
skip: bool,
|
||||||
pub scope: ExportScope,
|
pub scope: ExportScope,
|
||||||
}
|
}
|
||||||
@ -49,21 +49,32 @@ impl ExportedParams for ExportedModParams {
|
|||||||
|
|
||||||
fn from_info(info: ExportInfo) -> syn::Result<Self> {
|
fn from_info(info: ExportInfo) -> syn::Result<Self> {
|
||||||
let ExportInfo { items: attrs, .. } = info;
|
let ExportInfo { items: attrs, .. } = info;
|
||||||
let mut name = None;
|
let mut name = Default::default();
|
||||||
let mut skip = false;
|
let mut skip = false;
|
||||||
let mut scope = ExportScope::default();
|
let mut scope = None;
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
let AttrItem { key, value, .. } = attr;
|
let AttrItem { key, value, .. } = attr;
|
||||||
match (key.to_string().as_ref(), value) {
|
match (key.to_string().as_ref(), value) {
|
||||||
("name", Some(s)) => name = Some(s.value()),
|
("name", Some(s)) => {
|
||||||
|
let new_name = s.value();
|
||||||
|
if name == new_name {
|
||||||
|
return Err(syn::Error::new(key.span(), "conflicting name"));
|
||||||
|
}
|
||||||
|
name = new_name;
|
||||||
|
}
|
||||||
("name", None) => return Err(syn::Error::new(key.span(), "requires value")),
|
("name", None) => return Err(syn::Error::new(key.span(), "requires value")),
|
||||||
|
|
||||||
("skip", None) => skip = true,
|
("skip", None) => skip = true,
|
||||||
("skip", Some(s)) => return Err(syn::Error::new(s.span(), "extraneous value")),
|
("skip", Some(s)) => return Err(syn::Error::new(s.span(), "extraneous value")),
|
||||||
("export_prefix", Some(s)) => scope = ExportScope::Prefix(s.value()),
|
|
||||||
|
("export_prefix", Some(_)) | ("export_all", None) if scope.is_some() => {
|
||||||
|
return Err(syn::Error::new(key.span(), "duplicate export scope"));
|
||||||
|
}
|
||||||
|
("export_prefix", Some(s)) => scope = Some(ExportScope::Prefix(s.value())),
|
||||||
("export_prefix", None) => {
|
("export_prefix", None) => {
|
||||||
return Err(syn::Error::new(key.span(), "requires value"))
|
return Err(syn::Error::new(key.span(), "requires value"))
|
||||||
}
|
}
|
||||||
("export_all", None) => scope = ExportScope::All,
|
("export_all", None) => scope = Some(ExportScope::All),
|
||||||
("export_all", Some(s)) => {
|
("export_all", Some(s)) => {
|
||||||
return Err(syn::Error::new(s.span(), "extraneous value"))
|
return Err(syn::Error::new(s.span(), "extraneous value"))
|
||||||
}
|
}
|
||||||
@ -79,7 +90,7 @@ impl ExportedParams for ExportedModParams {
|
|||||||
Ok(ExportedModParams {
|
Ok(ExportedModParams {
|
||||||
name,
|
name,
|
||||||
skip,
|
skip,
|
||||||
scope,
|
scope: scope.unwrap_or_default(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -87,7 +98,7 @@ impl ExportedParams for ExportedModParams {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct Module {
|
pub(crate) struct Module {
|
||||||
mod_all: Option<syn::ItemMod>,
|
mod_all: syn::ItemMod,
|
||||||
fns: Vec<ExportedFn>,
|
fns: Vec<ExportedFn>,
|
||||||
consts: Vec<ExportedConst>,
|
consts: Vec<ExportedConst>,
|
||||||
submodules: Vec<Module>,
|
submodules: Vec<Module>,
|
||||||
@ -183,7 +194,7 @@ impl Parse for Module {
|
|||||||
fns = new_vec![];
|
fns = new_vec![];
|
||||||
}
|
}
|
||||||
Ok(Module {
|
Ok(Module {
|
||||||
mod_all: Some(mod_all),
|
mod_all,
|
||||||
fns,
|
fns,
|
||||||
consts,
|
consts,
|
||||||
submodules,
|
submodules,
|
||||||
@ -194,39 +205,27 @@ impl Parse for Module {
|
|||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
impl Module {
|
impl Module {
|
||||||
pub fn attrs(&self) -> Option<&Vec<syn::Attribute>> {
|
pub fn attrs(&self) -> &Vec<syn::Attribute> {
|
||||||
self.mod_all.as_ref().map(|m| &m.attrs)
|
&self.mod_all.attrs
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn module_name(&self) -> Option<&syn::Ident> {
|
pub fn module_name(&self) -> &syn::Ident {
|
||||||
self.mod_all.as_ref().map(|m| &m.ident)
|
&self.mod_all.ident
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exported_name(&self) -> Option<Cow<str>> {
|
pub fn exported_name(&self) -> Cow<str> {
|
||||||
if let Some(ref s) = self.params.name {
|
if !self.params.name.is_empty() {
|
||||||
Some(s.into())
|
self.params.name.as_str().into()
|
||||||
} else {
|
} else {
|
||||||
self.module_name().map(|m| m.to_string().into())
|
self.module_name().to_string().into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_scope(&mut self, parent_scope: &ExportScope) {
|
pub fn update_scope(&mut self, parent_scope: &ExportScope) {
|
||||||
let keep = match (self.params.skip, parent_scope) {
|
let keep = match (self.params.skip, parent_scope) {
|
||||||
(true, _) => false,
|
(true, _) => false,
|
||||||
(_, ExportScope::PubOnly) => {
|
(_, ExportScope::PubOnly) => matches!(self.mod_all.vis, syn::Visibility::Public(_)),
|
||||||
if let Some(ref mod_all) = self.mod_all {
|
(_, ExportScope::Prefix(s)) => self.mod_all.ident.to_string().starts_with(s),
|
||||||
matches!(mod_all.vis, syn::Visibility::Public(_))
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(_, ExportScope::Prefix(s)) => {
|
|
||||||
if let Some(ref mod_all) = self.mod_all {
|
|
||||||
mod_all.ident.to_string().starts_with(s)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(_, ExportScope::All) => true,
|
(_, ExportScope::All) => true,
|
||||||
};
|
};
|
||||||
self.params.skip = !keep;
|
self.params.skip = !keep;
|
||||||
@ -249,14 +248,13 @@ impl Module {
|
|||||||
|
|
||||||
// Extract the current structure of the module.
|
// Extract the current structure of the module.
|
||||||
let Module {
|
let Module {
|
||||||
mod_all,
|
mut mod_all,
|
||||||
mut fns,
|
mut fns,
|
||||||
consts,
|
consts,
|
||||||
mut submodules,
|
mut submodules,
|
||||||
params,
|
params,
|
||||||
..
|
..
|
||||||
} = self;
|
} = self;
|
||||||
let mut mod_all = mod_all.unwrap();
|
|
||||||
let mod_name = mod_all.ident.clone();
|
let mod_name = mod_all.ident.clone();
|
||||||
let (_, orig_content) = mod_all.content.take().unwrap();
|
let (_, orig_content) = mod_all.content.take().unwrap();
|
||||||
let mod_attrs = mem::take(&mut mod_all.attrs);
|
let mod_attrs = mem::take(&mut mod_all.attrs);
|
||||||
@ -299,8 +297,8 @@ impl Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> Option<&syn::Ident> {
|
pub fn name(&self) -> &syn::Ident {
|
||||||
self.mod_all.as_ref().map(|m| &m.ident)
|
&self.mod_all.ident
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn consts(&self) -> &[ExportedConst] {
|
pub fn consts(&self) -> &[ExportedConst] {
|
||||||
@ -317,10 +315,10 @@ impl Module {
|
|||||||
|
|
||||||
pub fn content(&self) -> Option<&Vec<syn::Item>> {
|
pub fn content(&self) -> Option<&Vec<syn::Item>> {
|
||||||
match self.mod_all {
|
match self.mod_all {
|
||||||
Some(syn::ItemMod {
|
syn::ItemMod {
|
||||||
content: Some((_, ref vec)),
|
content: Some((_, ref vec)),
|
||||||
..
|
..
|
||||||
}) => Some(vec),
|
} => Some(vec),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ pub(crate) fn generated_module_path(
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RegisterMacroInput = (syn::Expr, proc_macro2::TokenStream, syn::Path);
|
type RegisterMacroInput = (syn::Expr, proc_macro2::TokenStream, syn::Path);
|
||||||
|
|
||||||
pub fn parse_register_macro(
|
pub fn parse_register_macro(
|
||||||
args: proc_macro::TokenStream,
|
args: proc_macro::TokenStream,
|
||||||
) -> Result<RegisterMacroInput, syn::Error> {
|
) -> Result<RegisterMacroInput, syn::Error> {
|
||||||
|
@ -40,15 +40,13 @@ pub(crate) fn generate_body(
|
|||||||
if itemmod.skipped() {
|
if itemmod.skipped() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let module_name = itemmod.module_name().unwrap();
|
let module_name = itemmod.module_name();
|
||||||
let exported_name: syn::LitStr = if let Some(name) = itemmod.exported_name() {
|
let exported_name: syn::LitStr = syn::LitStr::new(
|
||||||
syn::LitStr::new(&name, proc_macro2::Span::call_site())
|
itemmod.exported_name().as_ref(),
|
||||||
} else {
|
proc_macro2::Span::call_site(),
|
||||||
syn::LitStr::new(&module_name.to_string(), proc_macro2::Span::call_site())
|
);
|
||||||
};
|
|
||||||
let cfg_attrs: Vec<&syn::Attribute> = itemmod
|
let cfg_attrs: Vec<&syn::Attribute> = itemmod
|
||||||
.attrs()
|
.attrs()
|
||||||
.unwrap()
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|&a| a.path.get_ident().map(|i| *i == "cfg").unwrap_or(false))
|
.filter(|&a| a.path.get_ident().map(|i| *i == "cfg").unwrap_or(false))
|
||||||
.collect();
|
.collect();
|
||||||
@ -158,12 +156,14 @@ pub(crate) fn generate_body(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ns) = function.params().namespace {
|
match function.params().namespace {
|
||||||
namespace = ns;
|
FnNamespaceAccess::Unset => (),
|
||||||
|
ns => namespace = ns,
|
||||||
}
|
}
|
||||||
|
|
||||||
let ns_str = syn::Ident::new(
|
let ns_str = syn::Ident::new(
|
||||||
match namespace {
|
match namespace {
|
||||||
|
FnNamespaceAccess::Unset => unreachable!(),
|
||||||
FnNamespaceAccess::Global => "Global",
|
FnNamespaceAccess::Global => "Global",
|
||||||
FnNamespaceAccess::Internal => "Internal",
|
FnNamespaceAccess::Internal => "Internal",
|
||||||
},
|
},
|
||||||
@ -256,11 +256,11 @@ pub(crate) fn check_rename_collisions(fns: &Vec<ExportedFn>) -> Result<(), syn::
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (name, fn_name) in names {
|
for (name, fn_name) in names {
|
||||||
let current_span = itemfn.params().span.as_ref().unwrap();
|
let current_span = itemfn.params().span.unwrap();
|
||||||
let key = make_key(&name, itemfn);
|
let key = make_key(&name, itemfn);
|
||||||
if let Some(other_span) = renames.insert(key, *current_span) {
|
if let Some(other_span) = renames.insert(key, current_span) {
|
||||||
let mut err = syn::Error::new(
|
let mut err = syn::Error::new(
|
||||||
*current_span,
|
current_span,
|
||||||
format!("duplicate Rhai signature for '{}'", &fn_name),
|
format!("duplicate Rhai signature for '{}'", &fn_name),
|
||||||
);
|
);
|
||||||
err.combine(syn::Error::new(
|
err.combine(syn::Error::new(
|
||||||
|
@ -291,6 +291,7 @@ fn multiple_fn_rename_test() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
mod export_by_prefix {
|
mod export_by_prefix {
|
||||||
use rhai::plugin::*;
|
use rhai::plugin::*;
|
||||||
|
|
||||||
#[export_module(export_prefix = "foo_")]
|
#[export_module(export_prefix = "foo_")]
|
||||||
pub mod my_adds {
|
pub mod my_adds {
|
||||||
use rhai::{FLOAT, INT};
|
use rhai::{FLOAT, INT};
|
||||||
@ -373,6 +374,7 @@ fn export_by_prefix_test() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
mod export_all {
|
mod export_all {
|
||||||
use rhai::plugin::*;
|
use rhai::plugin::*;
|
||||||
|
|
||||||
#[export_module(export_all)]
|
#[export_module(export_all)]
|
||||||
pub mod my_adds {
|
pub mod my_adds {
|
||||||
use rhai::{FLOAT, INT};
|
use rhai::{FLOAT, INT};
|
||||||
|
@ -73,8 +73,8 @@ fn one_fn_submodule_nested_attr_test() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
mod export_nested_by_prefix {
|
mod export_nested_by_prefix {
|
||||||
use rhai::plugin::*;
|
use rhai::plugin::*;
|
||||||
#[export_module(export_prefix = "foo_")]
|
|
||||||
|
|
||||||
|
#[export_module(export_prefix = "foo_")]
|
||||||
pub mod my_adds {
|
pub mod my_adds {
|
||||||
pub mod foo_first_adders {
|
pub mod foo_first_adders {
|
||||||
use rhai::{FLOAT, INT};
|
use rhai::{FLOAT, INT};
|
||||||
|
Loading…
Reference in New Issue
Block a user