Skip to content

Commit

Permalink
Class, Method and Property documentation (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
TitanNano committed Nov 20, 2023
1 parent a3bede0 commit c5c697c
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 33 deletions.
7 changes: 4 additions & 3 deletions derive/src/attribute_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,20 +246,21 @@ enum ExpEasingOpts {
}

#[derive(FromField, Debug)]
#[darling(forward_attrs(export, prop))]
#[darling(forward_attrs(export, prop, doc))]
pub struct FieldOpts {
pub ident: Option<syn::Ident>,
pub attrs: Vec<syn::Attribute>,
pub vis: syn::Visibility,
pub ty: syn::Type,
}

#[derive(FromDeriveInput)]
#[darling(supports(struct_any), attributes(script))]
#[derive(FromDeriveInput, Debug)]
#[darling(supports(struct_any), attributes(script), forward_attrs(doc))]
pub struct GodotScriptOpts {
pub ident: syn::Ident,
pub data: Data<util::Ignored, FieldOpts>,
pub base: Option<syn::Ident>,
pub attrs: Vec<syn::Attribute>,
}

#[derive(FromAttributes, Debug)]
Expand Down
14 changes: 13 additions & 1 deletion derive/src/impl_attribute.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use proc_macro2::TokenStream;
use quote::{quote, quote_spanned};
use quote::{quote, quote_spanned, ToTokens};
use syn::{parse_macro_input, spanned::Spanned, FnArg, ImplItem, ItemImpl, ReturnType, Type};

use crate::{
Expand Down Expand Up @@ -59,6 +59,7 @@ pub fn godot_script_impl(
exported: false,
hint: #property_hints::PROPERTY_HINT_NONE,
hint_string: "",
description: "",
},
},

Expand Down Expand Up @@ -94,6 +95,15 @@ pub fn godot_script_impl(
quote!(#godot_types::engine::global::MethodFlags::METHOD_FLAG_NORMAL)
};

let description = fnc.attrs.iter()
.filter(|attr| attr.path().is_ident("doc"))
.map(|attr| attr.meta.require_name_value().unwrap().value.to_token_stream())
.reduce(|mut acc, ident| {
acc.extend(quote!(, "\n", ));
acc.extend(ident);
acc
});

let metadata = quote_spanned! {
fnc.span() =>
::godot_rust_script::RustScriptMethodDesc {
Expand All @@ -105,8 +115,10 @@ pub fn godot_script_impl(
exported: false,
hint: #property_hints::PROPERTY_HINT_NONE,
hint_string: "",
description: "",
},
flags: #method_flag,
description: concat!(#description),
},
};

Expand Down
38 changes: 37 additions & 1 deletion derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ mod type_paths;
use attribute_ops::{FieldOpts, GodotScriptOpts};
use darling::{FromAttributes, FromDeriveInput};
use proc_macro2::TokenStream;
use quote::{quote, quote_spanned};
use quote::{quote, quote_spanned, ToTokens};
use syn::{parse_macro_input, spanned::Spanned, DeriveInput};
use type_paths::{godot_types, string_name_ty, variant_ty};

Expand Down Expand Up @@ -58,13 +58,31 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
ops.hint(field.ident.span())?
};

let description = field
.attrs
.iter()
.filter(|attr| attr.path().is_ident("doc"))
.map(|attr| {
attr.meta
.require_name_value()
.unwrap()
.value
.to_token_stream()
})
.reduce(|mut acc, comment| {
acc.extend(quote!(, "\n", ));
acc.extend(comment);
acc
});

let item = quote! {
::godot_rust_script::RustScriptPropDesc {
name: #name,
ty: #ty,
exported: #exported,
hint: #hint,
hint_string: #hint_string,
description: concat!(#description),
},
};

Expand All @@ -82,6 +100,23 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let properties_state_impl = derive_property_states_export(public_fields);
let default_impl = derive_default_with_base(&fields);

let description = opts
.attrs
.iter()
.filter(|attr| attr.path().is_ident("doc"))
.map(|attr| {
attr.meta
.require_name_value()
.unwrap()
.value
.to_token_stream()
})
.reduce(|mut acc, lit| {
acc.extend(quote!(,"\n",));
acc.extend(lit);
acc
});

let output = quote! {
impl ::godot_rust_script::GodotScript for #script_type_ident {
#get_fields_impl
Expand All @@ -104,6 +139,7 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
::godot_rust_script::register_script_class!(
#script_type_ident,
#base_class,
concat!(#description),
vec![
#field_metadata
]
Expand Down
10 changes: 9 additions & 1 deletion rust-script/src/library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{

#[macro_export]
macro_rules! register_script_class {
($class_name:ty, $base_name:ty, $props:expr) => {
($class_name:ty, $base_name:ty, $desc:expr, $props:expr) => {
$crate::private_export::plugin_add! {
__SCRIPT_REGISTRY in crate;
$crate::RegistryItem::Entry($crate::RustScriptEntry {
Expand All @@ -31,6 +31,7 @@ macro_rules! register_script_class {
$props
},
create_data: $crate::create_default_data_struct::<$class_name>,
description: $desc,
})
}
};
Expand Down Expand Up @@ -86,6 +87,7 @@ pub struct RustScriptEntry {
pub base_type_name: &'static str,
pub properties: fn() -> Vec<RustScriptPropDesc>,
pub create_data: fn(Gd<Object>) -> RemoteGodotScript_TO<'static, RBox<()>>,
pub description: &'static str,
}

#[derive(Debug)]
Expand All @@ -105,6 +107,7 @@ pub struct RustScriptPropDesc {
pub exported: bool,
pub hint: PropertyHint,
pub hint_string: &'static str,
pub description: &'static str,
}

impl RustScriptPropDesc {
Expand All @@ -122,6 +125,7 @@ impl RustScriptPropDesc {
},
hint: self.hint.ord(),
hint_string: self.hint_string.into(),
description: RStr::from_str(self.description),
}
}
}
Expand All @@ -131,6 +135,7 @@ pub struct RustScriptMethodDesc {
pub return_type: RustScriptPropDesc,
pub arguments: Vec<RustScriptPropDesc>,
pub flags: MethodFlags,
pub description: &'static str,
}

impl RustScriptMethodDesc {
Expand All @@ -146,6 +151,7 @@ impl RustScriptMethodDesc {
.into_iter()
.map(|arg| arg.into_property_info(class_name))
.collect(),
description: RStr::from_str(self.description),
}
}
}
Expand Down Expand Up @@ -188,13 +194,15 @@ pub fn assemble_metadata<'a>(
.collect();

let create_data = class.create_data;
let description = class.description;

RemoteScriptMetaData::new(
class.class_name.into(),
class.base_type_name.into(),
props,
methods,
create_data,
description.into(),
)
})
.collect()
Expand Down
92 changes: 90 additions & 2 deletions rust-script/src/runtime/metadata.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::rc::Rc;
use std::{ops::Deref, rc::Rc};

use abi_stable::std_types::RBox;
use godot::{
Expand All @@ -19,9 +19,12 @@ use crate::{
pub struct ScriptMetaData {
class_name: ClassName,
base_type_name: StringName,
properties_documented: Vec<Documented<PropertyInfo>>,
properties: Rc<Vec<PropertyInfo>>,
methods_documented: Vec<Documented<MethodInfo>>,
methods: Rc<Vec<MethodInfo>>,
create_data: CreateScriptInstanceData_TO<'static, RBox<()>>,
description: &'static str,
}

impl ScriptMetaData {
Expand All @@ -41,19 +44,39 @@ impl ScriptMetaData {
self.properties.clone()
}

pub fn properties_documented(&self) -> &[Documented<PropertyInfo>] {
&self.properties_documented
}

pub fn methods(&self) -> Rc<Vec<MethodInfo>> {
self.methods.clone()
}

pub fn methods_documented(&self) -> &[Documented<MethodInfo>] {
&self.methods_documented
}

pub fn description(&self) -> &'static str {
self.description
}
}

impl From<RemoteScriptMetaData> for ScriptMetaData {
fn from(value: RemoteScriptMetaData) -> Self {
Self {
class_name: ClassName::from_ascii_cstr(value.class_name.as_str().as_bytes()),
base_type_name: StringName::from(value.base_type_name.as_str()),
base_type_name: StringName::from(&value.base_type_name.as_str()),
properties_documented: value
.properties
.clone()
.into_iter()
.map(Into::into)
.collect(),
properties: Rc::new(value.properties.into_iter().map(Into::into).collect()),
methods_documented: value.methods.clone().into_iter().map(Into::into).collect(),
methods: Rc::new(value.methods.into_iter().map(Into::into).collect()),
create_data: value.create_data,
description: value.description.as_str(),
}
}
}
Expand Down Expand Up @@ -162,6 +185,55 @@ impl ToMethodDoc for MethodInfo {
}
}

impl<T: ToMethodDoc> ToMethodDoc for Documented<T> {
fn to_method_doc(&self) -> Dictionary {
self.inner
.to_method_doc()
.apply(|dict| dict.set("description", self.description))
}
}

#[derive(Debug)]
pub struct Documented<T> {
inner: T,
description: &'static str,
}

impl From<crate::script_registry::RemoteScriptPropertyInfo> for Documented<PropertyInfo> {
fn from(value: crate::script_registry::RemoteScriptPropertyInfo) -> Self {
Self {
description: value.description.as_str(),
inner: value.into(),
}
}
}

impl From<crate::script_registry::RemoteScriptMethodInfo> for Documented<MethodInfo> {
fn from(value: crate::script_registry::RemoteScriptMethodInfo) -> Self {
Self {
description: value.description.as_str(),
inner: value.into(),
}
}
}

impl<T> Deref for Documented<T> {
type Target = T;

fn deref(&self) -> &Self::Target {
&self.inner
}
}

impl<T: Clone> Clone for Documented<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
description: self.description,
}
}
}

pub trait ToArgumentDoc {
fn to_argument_doc(&self) -> Dictionary;
}
Expand All @@ -175,6 +247,14 @@ impl ToArgumentDoc for PropertyInfo {
}
}

impl<T: ToArgumentDoc> ToArgumentDoc for Documented<T> {
fn to_argument_doc(&self) -> Dictionary {
self.inner.to_argument_doc().apply(|dict| {
dict.set("description", self.description);
})
}
}

pub trait ToPropertyDoc {
fn to_property_doc(&self) -> Dictionary;
}
Expand All @@ -189,3 +269,11 @@ impl ToPropertyDoc for PropertyInfo {
})
}
}

impl<T: ToPropertyDoc> ToPropertyDoc for Documented<T> {
fn to_property_doc(&self) -> Dictionary {
self.inner
.to_property_doc()
.apply(|dict| dict.set("description", self.description))
}
}
2 changes: 1 addition & 1 deletion rust-script/src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ macro_rules! setup {
}
};
}

#[cfg(not(all(feature = "hot-reload", debug_assertions)))]
#[macro_export]
macro_rules! setup {
Expand Down
Loading

0 comments on commit c5c697c

Please sign in to comment.