Skip to content

Commit

Permalink
feat: add global functions to mdbook, allow documenting arguments and…
Browse files Browse the repository at this point in the history
… return values (#296)
  • Loading branch information
makspll authored Feb 20, 2025
1 parent 5f0a452 commit 630cac1
Show file tree
Hide file tree
Showing 24 changed files with 1,274 additions and 190 deletions.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ exclude = ["crates/bevy_api_gen", "crates/macro_tests"]
debug = 1
opt-level = 1

[profile.dev-debug]
inherits = "dev"
debug = true
opt-level = 0

[profile.dev.package."*"]
debug = 0
opt-level = 3
Expand Down
8 changes: 6 additions & 2 deletions crates/bevy_mod_scripting_core/src/docgen/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,14 @@ impl FunctionArgInfo {
}
}

#[derive(Debug, Clone, PartialEq, Reflect)]
#[derive(Debug, Clone, Reflect)]
/// Information about a function return value.
pub struct FunctionReturnInfo {
/// The type of the return value.
pub type_id: TypeId,
/// The type information of the return value.
#[reflect(ignore)]
pub type_info: Option<ThroughTypeInfo>,
}

impl Default for FunctionReturnInfo {
Expand All @@ -144,9 +147,10 @@ impl Default for FunctionReturnInfo {

impl FunctionReturnInfo {
/// Create a new function return info for a specific type.
pub fn new_for<T: 'static>() -> Self {
pub fn new_for<T: TypedThrough + 'static>() -> Self {
Self {
type_id: TypeId::of::<T>(),
type_info: Some(T::through_type_info()),
}
}
}
Expand Down
233 changes: 233 additions & 0 deletions crates/lad_backends/mdbook_lad_preprocessor/src/argument_visitor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
//! Defines a visitor for function arguments of the `LAD` format.
use ladfile::ArgumentVisitor;

use crate::markdown::MarkdownBuilder;

pub(crate) struct MarkdownArgumentVisitor<'a> {
ladfile: &'a ladfile::LadFile,
buffer: MarkdownBuilder,
}
impl<'a> MarkdownArgumentVisitor<'a> {
pub fn new(ladfile: &'a ladfile::LadFile) -> Self {
let mut builder = MarkdownBuilder::new();
builder.tight_inline().set_escape_mode(false);
Self {
ladfile,
buffer: builder,
}
}

pub fn build(mut self) -> String {
self.buffer.build()
}
}

impl ArgumentVisitor for MarkdownArgumentVisitor<'_> {
fn visit_lad_type_id(&mut self, type_id: &ladfile::LadTypeId) {
let mut buffer = String::new();

// Write identifier<Generic1TypeIdentifier, Generic2TypeIdentifier>
buffer.push_str(&self.ladfile.get_type_identifier(type_id));
if let Some(generics) = self.ladfile.get_type_generics(type_id) {
buffer.push('<');
for (i, generic) in generics.iter().enumerate() {
if i > 0 {
buffer.push_str(", ");
}
buffer.push_str(&self.ladfile.get_type_identifier(&generic.type_id));
}
buffer.push('>');
}

self.buffer.text(buffer);
}

fn walk_option(&mut self, inner: &ladfile::LadArgumentKind) {
// Write Optional<inner>
self.buffer.text("Optional<");
self.visit(inner);
self.buffer.text(">");
}

fn walk_vec(&mut self, inner: &ladfile::LadArgumentKind) {
// Write Vec<inner>
self.buffer.text("Vec<");
self.visit(inner);
self.buffer.text(">");
}

fn walk_hash_map(&mut self, key: &ladfile::LadArgumentKind, value: &ladfile::LadArgumentKind) {
// Write HashMap<key, value>
self.buffer.text("HashMap<");
self.visit(key);
self.buffer.text(", ");
self.visit(value);
self.buffer.text(">");
}

fn walk_tuple(&mut self, inner: &[ladfile::LadArgumentKind]) {
// Write (inner1, inner2, ...)
self.buffer.text("(");
for (idx, arg) in inner.iter().enumerate() {
self.visit(arg);
if idx < inner.len() - 1 {
self.buffer.text(", ");
}
}
self.buffer.text(")");
}

fn walk_array(&mut self, inner: &ladfile::LadArgumentKind, size: usize) {
// Write [inner; size]
self.buffer.text("[");
self.visit(inner);
self.buffer.text("; ");
self.buffer.text(size.to_string());
self.buffer.text("]");
}
}

#[cfg(test)]
mod test {
use ladfile::LadArgumentKind;

use super::*;

fn setup_ladfile() -> ladfile::LadFile {
// load test file from ../../../ladfile_builder/test_assets/
let ladfile = ladfile::EXAMPLE_LADFILE;
ladfile::parse_lad_file(ladfile).unwrap()
}

#[test]
fn test_visit_type_id() {
let ladfile = setup_ladfile();

let first_type_id = ladfile.types.first().unwrap().0;
let mut visitor = MarkdownArgumentVisitor::new(&ladfile);

visitor.visit_lad_type_id(first_type_id);
assert_eq!(visitor.buffer.build(), "EnumType");

visitor.buffer.clear();

let second_type_id = ladfile.types.iter().nth(1).unwrap().0;
visitor.visit_lad_type_id(second_type_id);
assert_eq!(visitor.buffer.build(), "StructType<usize>");
}

#[test]
fn test_visit_ref() {
let ladfile = setup_ladfile();

let first_type_id = ladfile.types.first().unwrap().0;
let mut visitor = MarkdownArgumentVisitor::new(&ladfile);

visitor.visit(&LadArgumentKind::Ref(first_type_id.clone()));
assert_eq!(visitor.buffer.build(), "EnumType");
}

#[test]
fn test_visit_mut() {
let ladfile = setup_ladfile();

let first_type_id = ladfile.types.first().unwrap().0;
let mut visitor = MarkdownArgumentVisitor::new(&ladfile);

visitor.visit(&LadArgumentKind::Mut(first_type_id.clone()));
assert_eq!(visitor.buffer.build(), "EnumType");
}

#[test]
fn test_visit_val() {
let ladfile = setup_ladfile();

let first_type_id = ladfile.types.first().unwrap().0;
let mut visitor = MarkdownArgumentVisitor::new(&ladfile);

visitor.visit(&LadArgumentKind::Val(first_type_id.clone()));
assert_eq!(visitor.buffer.build(), "EnumType");
}

#[test]
fn test_visit_option() {
let ladfile = setup_ladfile();

let mut visitor = MarkdownArgumentVisitor::new(&ladfile);

visitor.visit(&LadArgumentKind::Option(Box::new(
LadArgumentKind::Primitive(ladfile::LadBMSPrimitiveKind::Bool),
)));
assert_eq!(visitor.buffer.build(), "Optional<bool>");
}

#[test]
fn test_visit_vec() {
let ladfile = setup_ladfile();

let mut visitor = MarkdownArgumentVisitor::new(&ladfile);

visitor.visit(&LadArgumentKind::Vec(Box::new(LadArgumentKind::Primitive(
ladfile::LadBMSPrimitiveKind::Bool,
))));
assert_eq!(visitor.buffer.build(), "Vec<bool>");
}

#[test]
fn test_visit_hash_map() {
let ladfile = setup_ladfile();

let mut visitor = MarkdownArgumentVisitor::new(&ladfile);

visitor.visit(&LadArgumentKind::HashMap(
Box::new(LadArgumentKind::Primitive(
ladfile::LadBMSPrimitiveKind::Bool,
)),
Box::new(LadArgumentKind::Primitive(
ladfile::LadBMSPrimitiveKind::String,
)),
));
assert_eq!(visitor.buffer.build(), "HashMap<bool, String>");
}

#[test]
fn test_visit_tuple() {
let ladfile = setup_ladfile();

let mut visitor = MarkdownArgumentVisitor::new(&ladfile);

visitor.visit(&LadArgumentKind::Tuple(vec![
LadArgumentKind::Primitive(ladfile::LadBMSPrimitiveKind::Bool),
LadArgumentKind::Primitive(ladfile::LadBMSPrimitiveKind::String),
]));
assert_eq!(visitor.buffer.build(), "(bool, String)");
}

#[test]
fn test_visit_array() {
let ladfile = setup_ladfile();

let mut visitor = MarkdownArgumentVisitor::new(&ladfile);

visitor.visit(&LadArgumentKind::Array(
Box::new(LadArgumentKind::Primitive(
ladfile::LadBMSPrimitiveKind::Bool,
)),
5,
));
assert_eq!(visitor.buffer.build(), "[bool; 5]");
}

#[test]
fn test_visit_unknown() {
let ladfile = setup_ladfile();

let mut visitor = MarkdownArgumentVisitor::new(&ladfile);

let first_type_id = ladfile.types.first().unwrap().0;

visitor.visit(&LadArgumentKind::Unknown(first_type_id.clone()));
assert_eq!(visitor.buffer.build(), "EnumType");
}
}
16 changes: 14 additions & 2 deletions crates/lad_backends/mdbook_lad_preprocessor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#![allow(missing_docs)]

use mdbook::{errors::Error, preprocess::Preprocessor};
mod argument_visitor;
mod markdown;
mod sections;

Expand Down Expand Up @@ -31,6 +32,10 @@ impl Preprocessor for LADPreprocessor {

if !is_lad_chapter {
log::debug!("Skipping non-LAD chapter: {:?}", chapter.source_path);
log::trace!(
"Non-LAD chapter: {}",
serde_json::to_string_pretty(&chapter).unwrap_or_default()
);
return;
}

Expand All @@ -45,7 +50,10 @@ impl Preprocessor for LADPreprocessor {
}
};

log::debug!("Parsed LAD file: {:?}", lad);
log::debug!(
"Parsed LAD file: {}",
serde_json::to_string_pretty(&lad).unwrap_or_default()
);

let sections = sections::lad_file_to_sections(&lad, Some(chapter_title));

Expand All @@ -58,7 +66,11 @@ impl Preprocessor for LADPreprocessor {
None,
);

log::debug!("New chapter: {:?}", new_chapter);
// serialize chapter to json
log::debug!(
"New chapter: {}",
serde_json::to_string_pretty(&new_chapter).unwrap_or_default()
);

*chapter = new_chapter;
}
Expand Down
Loading

0 comments on commit 630cac1

Please sign in to comment.