bevy/crates/bevy_reflect/src/fields.rs
Gino Valente a658bfef19 bevy_reflect: Reflect doc comments (#6234)
# Objective

Resolves #6197

Make it so that doc comments can be retrieved via reflection.

## Solution

Adds the new `documentation` feature to `bevy_reflect` (disabled by default).

When enabled, documentation can be found using `TypeInfo::doc` for reflected types:

```rust
/// Some struct.
///
/// # Example
///
/// ```ignore
/// let some_struct = SomeStruct;
/// ```
#[derive(Reflect)]
struct SomeStruct;

let info = <SomeStruct as Typed>::type_info();
assert_eq!(
    Some(" Some struct.\n\n # Example\n\n ```ignore\n let some_struct = SomeStruct;\n ```"),
    info.docs()
);
```

### Notes for Reviewers

The bulk of the files simply added the same 16 lines of code (with slightly different documentation). Most of the real changes occur in the `bevy_reflect_derive` files as well as in the added tests.

---

## Changelog

* Added `documentation` feature to `bevy_reflect`
* Added `TypeInfo::docs` method (and similar methods for all info types)
2022-10-18 13:49:57 +00:00

115 lines
2.8 KiB
Rust

use crate::Reflect;
use std::any::{Any, TypeId};
/// The named field of a reflected struct.
#[derive(Clone, Debug)]
pub struct NamedField {
name: &'static str,
type_name: &'static str,
type_id: TypeId,
#[cfg(feature = "documentation")]
docs: Option<&'static str>,
}
impl NamedField {
/// Create a new [`NamedField`].
pub fn new<T: Reflect>(name: &'static str) -> Self {
Self {
name,
type_name: std::any::type_name::<T>(),
type_id: TypeId::of::<T>(),
#[cfg(feature = "documentation")]
docs: None,
}
}
/// Sets the docstring for this field.
#[cfg(feature = "documentation")]
pub fn with_docs(self, docs: Option<&'static str>) -> Self {
Self { docs, ..self }
}
/// The name of the field.
pub fn name(&self) -> &'static str {
self.name
}
/// The [type name] of the field.
///
/// [type name]: std::any::type_name
pub fn type_name(&self) -> &'static str {
self.type_name
}
/// The [`TypeId`] of the field.
pub fn type_id(&self) -> TypeId {
self.type_id
}
/// Check if the given type matches the field type.
pub fn is<T: Any>(&self) -> bool {
TypeId::of::<T>() == self.type_id
}
/// The docstring of this field, if any.
#[cfg(feature = "documentation")]
pub fn docs(&self) -> Option<&'static str> {
self.docs
}
}
/// The unnamed field of a reflected tuple or tuple struct.
#[derive(Clone, Debug)]
pub struct UnnamedField {
index: usize,
type_name: &'static str,
type_id: TypeId,
#[cfg(feature = "documentation")]
docs: Option<&'static str>,
}
impl UnnamedField {
pub fn new<T: Reflect>(index: usize) -> Self {
Self {
index,
type_name: std::any::type_name::<T>(),
type_id: TypeId::of::<T>(),
#[cfg(feature = "documentation")]
docs: None,
}
}
/// Sets the docstring for this field.
#[cfg(feature = "documentation")]
pub fn with_docs(self, docs: Option<&'static str>) -> Self {
Self { docs, ..self }
}
/// Returns the index of the field.
pub fn index(&self) -> usize {
self.index
}
/// The [type name] of the field.
///
/// [type name]: std::any::type_name
pub fn type_name(&self) -> &'static str {
self.type_name
}
/// The [`TypeId`] of the field.
pub fn type_id(&self) -> TypeId {
self.type_id
}
/// Check if the given type matches the field type.
pub fn is<T: Any>(&self) -> bool {
TypeId::of::<T>() == self.type_id
}
/// The docstring of this field, if any.
#[cfg(feature = "documentation")]
pub fn docs(&self) -> Option<&'static str> {
self.docs
}
}