 a658bfef19
			
		
	
	
		a658bfef19
		
	
	
	
	
		
			
			# 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)
		
			
				
	
	
		
			251 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			251 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use crate::{NamedField, UnnamedField};
 | |
| use bevy_utils::HashMap;
 | |
| use std::slice::Iter;
 | |
| 
 | |
| /// Describes the form of an enum variant.
 | |
| #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
 | |
| pub enum VariantType {
 | |
|     /// Struct enums take the form:
 | |
|     ///
 | |
|     /// ```
 | |
|     /// enum MyEnum {
 | |
|     ///   A {
 | |
|     ///     foo: usize
 | |
|     ///   }
 | |
|     /// }
 | |
|     /// ```
 | |
|     Struct,
 | |
|     /// Tuple enums take the form:
 | |
|     ///
 | |
|     /// ```
 | |
|     /// enum MyEnum {
 | |
|     ///   A(usize)
 | |
|     /// }
 | |
|     /// ```
 | |
|     Tuple,
 | |
|     /// Unit enums take the form:
 | |
|     ///
 | |
|     /// ```
 | |
|     /// enum MyEnum {
 | |
|     ///   A
 | |
|     /// }
 | |
|     /// ```
 | |
|     Unit,
 | |
| }
 | |
| 
 | |
| /// A container for compile-time enum variant info.
 | |
| #[derive(Clone, Debug)]
 | |
| pub enum VariantInfo {
 | |
|     /// Struct enums take the form:
 | |
|     ///
 | |
|     /// ```
 | |
|     /// enum MyEnum {
 | |
|     ///   A {
 | |
|     ///     foo: usize
 | |
|     ///   }
 | |
|     /// }
 | |
|     /// ```
 | |
|     Struct(StructVariantInfo),
 | |
|     /// Tuple enums take the form:
 | |
|     ///
 | |
|     /// ```
 | |
|     /// enum MyEnum {
 | |
|     ///   A(usize)
 | |
|     /// }
 | |
|     /// ```
 | |
|     Tuple(TupleVariantInfo),
 | |
|     /// Unit enums take the form:
 | |
|     ///
 | |
|     /// ```
 | |
|     /// enum MyEnum {
 | |
|     ///   A
 | |
|     /// }
 | |
|     /// ```
 | |
|     Unit(UnitVariantInfo),
 | |
| }
 | |
| 
 | |
| impl VariantInfo {
 | |
|     pub fn name(&self) -> &'static str {
 | |
|         match self {
 | |
|             Self::Struct(info) => info.name(),
 | |
|             Self::Tuple(info) => info.name(),
 | |
|             Self::Unit(info) => info.name(),
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// The docstring of the underlying variant, if any.
 | |
|     #[cfg(feature = "documentation")]
 | |
|     pub fn docs(&self) -> Option<&str> {
 | |
|         match self {
 | |
|             Self::Struct(info) => info.docs(),
 | |
|             Self::Tuple(info) => info.docs(),
 | |
|             Self::Unit(info) => info.docs(),
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Type info for struct variants.
 | |
| #[derive(Clone, Debug)]
 | |
| pub struct StructVariantInfo {
 | |
|     name: &'static str,
 | |
|     fields: Box<[NamedField]>,
 | |
|     field_indices: HashMap<&'static str, usize>,
 | |
|     #[cfg(feature = "documentation")]
 | |
|     docs: Option<&'static str>,
 | |
| }
 | |
| 
 | |
| impl StructVariantInfo {
 | |
|     /// Create a new [`StructVariantInfo`].
 | |
|     pub fn new(name: &'static str, fields: &[NamedField]) -> Self {
 | |
|         let field_indices = Self::collect_field_indices(fields);
 | |
|         Self {
 | |
|             name,
 | |
|             fields: fields.to_vec().into_boxed_slice(),
 | |
|             field_indices,
 | |
|             #[cfg(feature = "documentation")]
 | |
|             docs: None,
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Sets the docstring for this variant.
 | |
|     #[cfg(feature = "documentation")]
 | |
|     pub fn with_docs(self, docs: Option<&'static str>) -> Self {
 | |
|         Self { docs, ..self }
 | |
|     }
 | |
| 
 | |
|     /// The name of this variant.
 | |
|     pub fn name(&self) -> &'static str {
 | |
|         self.name
 | |
|     }
 | |
| 
 | |
|     /// Get the field with the given name.
 | |
|     pub fn field(&self, name: &str) -> Option<&NamedField> {
 | |
|         self.field_indices
 | |
|             .get(name)
 | |
|             .map(|index| &self.fields[*index])
 | |
|     }
 | |
| 
 | |
|     /// Get the field at the given index.
 | |
|     pub fn field_at(&self, index: usize) -> Option<&NamedField> {
 | |
|         self.fields.get(index)
 | |
|     }
 | |
| 
 | |
|     /// Get the index of the field with the given name.
 | |
|     pub fn index_of(&self, name: &str) -> Option<usize> {
 | |
|         self.field_indices.get(name).copied()
 | |
|     }
 | |
| 
 | |
|     /// Iterate over the fields of this variant.
 | |
|     pub fn iter(&self) -> Iter<'_, NamedField> {
 | |
|         self.fields.iter()
 | |
|     }
 | |
| 
 | |
|     /// The total number of fields in this variant.
 | |
|     pub fn field_len(&self) -> usize {
 | |
|         self.fields.len()
 | |
|     }
 | |
| 
 | |
|     fn collect_field_indices(fields: &[NamedField]) -> HashMap<&'static str, usize> {
 | |
|         fields
 | |
|             .iter()
 | |
|             .enumerate()
 | |
|             .map(|(index, field)| (field.name(), index))
 | |
|             .collect()
 | |
|     }
 | |
| 
 | |
|     /// The docstring of this variant, if any.
 | |
|     #[cfg(feature = "documentation")]
 | |
|     pub fn docs(&self) -> Option<&'static str> {
 | |
|         self.docs
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Type info for tuple variants.
 | |
| #[derive(Clone, Debug)]
 | |
| pub struct TupleVariantInfo {
 | |
|     name: &'static str,
 | |
|     fields: Box<[UnnamedField]>,
 | |
|     #[cfg(feature = "documentation")]
 | |
|     docs: Option<&'static str>,
 | |
| }
 | |
| 
 | |
| impl TupleVariantInfo {
 | |
|     /// Create a new [`TupleVariantInfo`].
 | |
|     pub fn new(name: &'static str, fields: &[UnnamedField]) -> Self {
 | |
|         Self {
 | |
|             name,
 | |
|             fields: fields.to_vec().into_boxed_slice(),
 | |
|             #[cfg(feature = "documentation")]
 | |
|             docs: None,
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Sets the docstring for this variant.
 | |
|     #[cfg(feature = "documentation")]
 | |
|     pub fn with_docs(self, docs: Option<&'static str>) -> Self {
 | |
|         Self { docs, ..self }
 | |
|     }
 | |
| 
 | |
|     /// The name of this variant.
 | |
|     pub fn name(&self) -> &'static str {
 | |
|         self.name
 | |
|     }
 | |
| 
 | |
|     /// Get the field at the given index.
 | |
|     pub fn field_at(&self, index: usize) -> Option<&UnnamedField> {
 | |
|         self.fields.get(index)
 | |
|     }
 | |
| 
 | |
|     /// Iterate over the fields of this variant.
 | |
|     pub fn iter(&self) -> Iter<'_, UnnamedField> {
 | |
|         self.fields.iter()
 | |
|     }
 | |
| 
 | |
|     /// The total number of fields in this variant.
 | |
|     pub fn field_len(&self) -> usize {
 | |
|         self.fields.len()
 | |
|     }
 | |
| 
 | |
|     /// The docstring of this variant, if any.
 | |
|     #[cfg(feature = "documentation")]
 | |
|     pub fn docs(&self) -> Option<&'static str> {
 | |
|         self.docs
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Type info for unit variants.
 | |
| #[derive(Clone, Debug)]
 | |
| pub struct UnitVariantInfo {
 | |
|     name: &'static str,
 | |
|     #[cfg(feature = "documentation")]
 | |
|     docs: Option<&'static str>,
 | |
| }
 | |
| 
 | |
| impl UnitVariantInfo {
 | |
|     /// Create a new [`UnitVariantInfo`].
 | |
|     pub fn new(name: &'static str) -> Self {
 | |
|         Self {
 | |
|             name,
 | |
|             #[cfg(feature = "documentation")]
 | |
|             docs: None,
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Sets the docstring for this variant.
 | |
|     #[cfg(feature = "documentation")]
 | |
|     pub fn with_docs(self, docs: Option<&'static str>) -> Self {
 | |
|         Self { docs, ..self }
 | |
|     }
 | |
| 
 | |
|     /// The name of this variant.
 | |
|     pub fn name(&self) -> &'static str {
 | |
|         self.name
 | |
|     }
 | |
| 
 | |
|     /// The docstring of this variant, if any.
 | |
|     #[cfg(feature = "documentation")]
 | |
|     pub fn docs(&self) -> Option<&'static str> {
 | |
|         self.docs
 | |
|     }
 | |
| }
 |