Add documentation to Module.
This commit is contained in:
parent
276d4457c3
commit
492d79d8a2
@ -17,6 +17,7 @@ New features
|
|||||||
|
|
||||||
* A new feature, `no_custom_syntax`, is added to remove custom syntax support from Rhai for applications that do not require it (which should be most).
|
* A new feature, `no_custom_syntax`, is added to remove custom syntax support from Rhai for applications that do not require it (which should be most).
|
||||||
* Comment lines beginning with `//!` (requires the `metadata` feature) are now collected as the script file's _module documentation_.
|
* Comment lines beginning with `//!` (requires the `metadata` feature) are now collected as the script file's _module documentation_.
|
||||||
|
* `AST` and `Module` have methods to access and manipulate documentation.
|
||||||
|
|
||||||
Enhancements
|
Enhancements
|
||||||
------------
|
------------
|
||||||
|
@ -195,6 +195,7 @@ impl AST {
|
|||||||
/// Leading white-spaces are stripped, and each line always starts with `//!`.
|
/// Leading white-spaces are stripped, and each line always starts with `//!`.
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
#[must_use]
|
||||||
pub fn doc(&self) -> &str {
|
pub fn doc(&self) -> &str {
|
||||||
&self.doc
|
&self.doc
|
||||||
}
|
}
|
||||||
@ -211,6 +212,7 @@ impl AST {
|
|||||||
/// Only available under `metadata`.
|
/// Only available under `metadata`.
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
#[must_use]
|
||||||
pub(crate) fn doc_mut(&mut self) -> &mut SmartString {
|
pub(crate) fn doc_mut(&mut self) -> &mut SmartString {
|
||||||
&mut self.doc
|
&mut self.doc
|
||||||
}
|
}
|
||||||
|
@ -250,6 +250,9 @@ pub struct Module {
|
|||||||
/// ID identifying the module.
|
/// ID identifying the module.
|
||||||
/// No ID if string is empty.
|
/// No ID if string is empty.
|
||||||
id: Identifier,
|
id: Identifier,
|
||||||
|
/// Module documentation.
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
doc: crate::SmartString,
|
||||||
/// Is this module internal?
|
/// Is this module internal?
|
||||||
pub(crate) internal: bool,
|
pub(crate) internal: bool,
|
||||||
/// Is this module part of a standard library?
|
/// Is this module part of a standard library?
|
||||||
@ -290,31 +293,27 @@ impl fmt::Debug for Module {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let mut d = f.debug_struct("Module");
|
let mut d = f.debug_struct("Module");
|
||||||
|
|
||||||
if !self.id.is_empty() {
|
d.field("id", &self.id)
|
||||||
d.field("id", &self.id);
|
.field(
|
||||||
}
|
|
||||||
if !self.modules.is_empty() {
|
|
||||||
d.field(
|
|
||||||
"modules",
|
"modules",
|
||||||
&self
|
&self
|
||||||
.modules
|
.modules
|
||||||
.keys()
|
.keys()
|
||||||
.map(|m| m.as_str())
|
.map(|m| m.as_str())
|
||||||
.collect::<BTreeSet<_>>(),
|
.collect::<BTreeSet<_>>(),
|
||||||
);
|
)
|
||||||
}
|
.field("vars", &self.variables)
|
||||||
if !self.variables.is_empty() {
|
.field(
|
||||||
d.field("vars", &self.variables);
|
|
||||||
}
|
|
||||||
if !self.functions.is_empty() {
|
|
||||||
d.field(
|
|
||||||
"functions",
|
"functions",
|
||||||
&self
|
&self
|
||||||
.iter_fn()
|
.iter_fn()
|
||||||
.map(|f| f.func.to_string())
|
.map(|f| f.func.to_string())
|
||||||
.collect::<BTreeSet<_>>(),
|
.collect::<BTreeSet<_>>(),
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
d.field("doc", &self.doc);
|
||||||
|
|
||||||
d.finish()
|
d.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -363,6 +362,8 @@ impl Module {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: Identifier::new_const(),
|
id: Identifier::new_const(),
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
doc: crate::SmartString::new_const(),
|
||||||
internal: false,
|
internal: false,
|
||||||
standard: false,
|
standard: false,
|
||||||
custom_types: CustomTypesCollection::new(),
|
custom_types: CustomTypesCollection::new(),
|
||||||
@ -423,6 +424,7 @@ impl Module {
|
|||||||
self.id = id.into();
|
self.id = id.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear the ID of the [`Module`].
|
/// Clear the ID of the [`Module`].
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -441,10 +443,68 @@ impl Module {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the documentation of the [`Module`], if any.
|
||||||
|
/// Exported under the `metadata` feature only.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use rhai::Module;
|
||||||
|
/// let mut module = Module::new();
|
||||||
|
/// module.set_doc("//! This is my special module.");
|
||||||
|
/// assert_eq!(module.doc(), "//! This is my special module.");
|
||||||
|
/// ```
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
|
pub fn doc(&self) -> &str {
|
||||||
|
&self.doc
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the documentation of the [`Module`].
|
||||||
|
/// Exported under the `metadata` feature only.
|
||||||
|
///
|
||||||
|
/// If the string is empty, it is equivalent to clearing the documentation.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use rhai::Module;
|
||||||
|
/// let mut module = Module::new();
|
||||||
|
/// module.set_doc("//! This is my special module.");
|
||||||
|
/// assert_eq!(module.doc(), "//! This is my special module.");
|
||||||
|
/// ```
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn set_doc(&mut self, doc: impl Into<crate::SmartString>) -> &mut Self {
|
||||||
|
self.doc = doc.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clear the documentation of the [`Module`].
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use rhai::Module;
|
||||||
|
/// let mut module = Module::new();
|
||||||
|
/// module.set_doc("//! This is my special module.");
|
||||||
|
/// assert_eq!(module.doc(), "//! This is my special module.");
|
||||||
|
/// module.clear_id();
|
||||||
|
/// assert_eq!(module.doc(), "");
|
||||||
|
/// ```
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn clear_doc(&mut self) -> &mut Self {
|
||||||
|
self.doc.clear();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Clear the [`Module`].
|
/// Clear the [`Module`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.id.clear();
|
self.id.clear();
|
||||||
|
self.doc.clear();
|
||||||
self.internal = false;
|
self.internal = false;
|
||||||
self.standard = false;
|
self.standard = false;
|
||||||
self.custom_types.clear();
|
self.custom_types.clear();
|
||||||
@ -1563,6 +1623,15 @@ impl Module {
|
|||||||
self.all_type_iterators.clear();
|
self.all_type_iterators.clear();
|
||||||
self.indexed = false;
|
self.indexed = false;
|
||||||
self.contains_indexed_global_functions = false;
|
self.contains_indexed_global_functions = false;
|
||||||
|
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
if !other.doc.is_empty() {
|
||||||
|
if !self.doc.is_empty() {
|
||||||
|
self.doc.push('\n');
|
||||||
|
}
|
||||||
|
self.doc.push_str(&other.doc);
|
||||||
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1584,6 +1653,15 @@ impl Module {
|
|||||||
self.all_type_iterators.clear();
|
self.all_type_iterators.clear();
|
||||||
self.indexed = false;
|
self.indexed = false;
|
||||||
self.contains_indexed_global_functions = false;
|
self.contains_indexed_global_functions = false;
|
||||||
|
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
if !other.doc.is_empty() {
|
||||||
|
if !self.doc.is_empty() {
|
||||||
|
self.doc.push('\n');
|
||||||
|
}
|
||||||
|
self.doc.push_str(&other.doc);
|
||||||
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1614,6 +1692,15 @@ impl Module {
|
|||||||
self.all_type_iterators.clear();
|
self.all_type_iterators.clear();
|
||||||
self.indexed = false;
|
self.indexed = false;
|
||||||
self.contains_indexed_global_functions = false;
|
self.contains_indexed_global_functions = false;
|
||||||
|
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
if !other.doc.is_empty() {
|
||||||
|
if !self.doc.is_empty() {
|
||||||
|
self.doc.push('\n');
|
||||||
|
}
|
||||||
|
self.doc.push_str(&other.doc);
|
||||||
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1667,6 +1754,15 @@ impl Module {
|
|||||||
self.all_type_iterators.clear();
|
self.all_type_iterators.clear();
|
||||||
self.indexed = false;
|
self.indexed = false;
|
||||||
self.contains_indexed_global_functions = false;
|
self.contains_indexed_global_functions = false;
|
||||||
|
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
if !other.doc.is_empty() {
|
||||||
|
if !self.doc.is_empty() {
|
||||||
|
self.doc.push('\n');
|
||||||
|
}
|
||||||
|
self.doc.push_str(&other.doc);
|
||||||
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1978,6 +2074,9 @@ impl Module {
|
|||||||
|
|
||||||
module.set_id(ast.source_raw().clone());
|
module.set_id(ast.source_raw().clone());
|
||||||
|
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
module.set_doc(ast.doc());
|
||||||
|
|
||||||
module.build_index();
|
module.build_index();
|
||||||
|
|
||||||
Ok(module)
|
Ok(module)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#![cfg(feature = "metadata")]
|
#![cfg(feature = "metadata")]
|
||||||
|
|
||||||
use crate::module::{calc_native_fn_hash, FuncInfo};
|
use crate::module::{calc_native_fn_hash, FuncInfo};
|
||||||
use crate::{calc_fn_hash, Engine, AST};
|
use crate::{calc_fn_hash, Engine, SmartString, AST};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -158,6 +158,9 @@ impl<'a> From<&'a FuncInfo> for FnMetadata<'a> {
|
|||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
struct ModuleMetadata<'a> {
|
struct ModuleMetadata<'a> {
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
#[serde(skip_serializing_if = "SmartString::is_empty")]
|
||||||
|
pub doc: SmartString,
|
||||||
#[serde(skip_serializing_if = "BTreeMap::is_empty")]
|
#[serde(skip_serializing_if = "BTreeMap::is_empty")]
|
||||||
pub modules: BTreeMap<&'a str, Self>,
|
pub modules: BTreeMap<&'a str, Self>,
|
||||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||||
@ -168,6 +171,8 @@ impl ModuleMetadata<'_> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
doc: SmartString::new_const(),
|
||||||
modules: BTreeMap::new(),
|
modules: BTreeMap::new(),
|
||||||
functions: Vec::new(),
|
functions: Vec::new(),
|
||||||
}
|
}
|
||||||
@ -180,6 +185,7 @@ impl<'a> From<&'a crate::Module> for ModuleMetadata<'a> {
|
|||||||
functions.sort();
|
functions.sort();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
doc: module.doc().into(),
|
||||||
modules: module
|
modules: module
|
||||||
.iter_sub_modules()
|
.iter_sub_modules()
|
||||||
.map(|(name, m)| (name, m.as_ref().into()))
|
.map(|(name, m)| (name, m.as_ref().into()))
|
||||||
@ -240,6 +246,11 @@ impl Engine {
|
|||||||
|
|
||||||
global.functions.sort();
|
global.functions.sort();
|
||||||
|
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
{
|
||||||
|
global.doc = ast.doc().into();
|
||||||
|
}
|
||||||
|
|
||||||
serde_json::to_string_pretty(&global)
|
serde_json::to_string_pretty(&global)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user