#![allow(missing_docs)]
pub mod code;
pub mod markdown;
pub mod multipage;
mod parse;
#[cfg(test)]
mod tests;
use std::iter;
use allocative::Allocative;
pub use parse::DocStringKind;
use starlark_map::small_map::SmallMap;
use crate as starlark;
use crate::eval::runtime::params::display::iter_fmt_param_spec;
pub use crate::eval::runtime::params::display::FmtParam;
use crate::typing::Ty;
use crate::values::type_repr::StarlarkTypeRepr;
use crate::values::StarlarkValue;
use crate::values::Trace;
use crate::values::Value;
#[derive(Debug, Clone, PartialEq, Trace, Default, Allocative)]
pub struct DocString {
pub summary: String,
pub details: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Default, Allocative)]
pub struct DocModule {
pub docs: Option<DocString>,
pub members: SmallMap<String, DocItem>,
}
#[derive(Debug, Clone, PartialEq, Default, Allocative)]
pub struct DocFunction {
pub docs: Option<DocString>,
pub params: DocParams,
pub ret: DocReturn,
}
impl DocFunction {
pub fn find_param_with_name(&self, param_name: &str) -> Option<(String, &DocParam)> {
self.params
.doc_params_with_starred_names()
.find(|(_, p)| p.name == param_name)
}
}
#[derive(Debug, Clone, PartialEq, Default, Allocative)]
pub struct DocParams {
pub pos_only: Vec<DocParam>,
pub pos_or_named: Vec<DocParam>,
pub args: Option<DocParam>,
pub named_only: Vec<DocParam>,
pub kwargs: Option<DocParam>,
}
impl DocParams {
pub(crate) fn doc_params(&self) -> impl Iterator<Item = &DocParam> {
iter::empty()
.chain(&self.pos_only)
.chain(&self.pos_or_named)
.chain(&self.args)
.chain(&self.named_only)
.chain(&self.kwargs)
}
pub(crate) fn doc_params_with_starred_names(
&self,
) -> impl Iterator<Item = (String, &DocParam)> {
iter::empty()
.chain(self.pos_only.iter().map(|p| (p.name.clone(), p)))
.chain(self.pos_or_named.iter().map(|p| (p.name.clone(), p)))
.chain(self.args.iter().map(|p| (format!("*{}", p.name), p)))
.chain(self.named_only.iter().map(|p| (p.name.clone(), p)))
.chain(self.kwargs.iter().map(|p| (format!("**{}", p.name), p)))
}
pub(crate) fn doc_params_mut(&mut self) -> impl Iterator<Item = &mut DocParam> {
iter::empty()
.chain(&mut self.pos_only)
.chain(&mut self.pos_or_named)
.chain(&mut self.args)
.chain(&mut self.named_only)
.chain(&mut self.kwargs)
}
pub fn regular_params(&self) -> impl Iterator<Item = &DocParam> {
iter::empty()
.chain(&self.pos_only)
.chain(&self.pos_or_named)
.chain(&self.named_only)
}
pub fn fmt_params(&self) -> impl Iterator<Item = FmtParam<&'_ DocParam>> {
iter_fmt_param_spec(
&self.pos_only,
&self.pos_or_named,
self.args.as_ref(),
&self.named_only,
self.kwargs.as_ref(),
)
}
}
#[derive(Debug, Clone, PartialEq, Allocative)]
pub struct DocParam {
pub name: String,
pub docs: Option<DocString>,
pub typ: Ty,
pub default_value: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Allocative)]
pub struct DocReturn {
pub docs: Option<DocString>,
pub typ: Ty,
}
impl Default for DocReturn {
fn default() -> Self {
DocReturn {
docs: None,
typ: Ty::any(),
}
}
}
#[derive(Debug, Clone, PartialEq, Allocative)]
pub struct DocProperty {
pub docs: Option<DocString>,
pub typ: Ty,
}
#[derive(Debug, Clone, PartialEq, Allocative)]
pub enum DocMember {
Property(DocProperty),
Function(DocFunction),
}
impl DocMember {
pub(crate) fn from_value(value: Value) -> Self {
match value.documentation() {
DocItem::Member(x) => x,
_ => DocMember::Property(DocProperty {
docs: None,
typ: value.get_type_starlark_repr(),
}),
}
}
}
#[derive(Debug, Clone, PartialEq, Allocative)]
pub struct DocType {
pub docs: Option<DocString>,
pub members: SmallMap<String, DocMember>,
pub ty: Ty,
pub constructor: Option<DocFunction>,
}
impl DocType {
pub fn from_starlark_value<T: StarlarkValue<'static>>() -> DocType {
let ty = T::starlark_type_repr();
match T::get_methods() {
Some(methods) => methods.documentation(ty),
None => DocType {
docs: None,
members: SmallMap::new(),
ty,
constructor: None,
},
}
}
}
#[derive(Debug, Clone, PartialEq, Allocative)]
pub enum DocItem {
Module(DocModule),
Type(DocType),
Member(DocMember),
}
impl DocItem {
pub fn get_doc_string(&self) -> Option<&DocString> {
match self {
DocItem::Module(m) => m.docs.as_ref(),
DocItem::Type(o) => o.docs.as_ref(),
DocItem::Member(DocMember::Function(f)) => f.docs.as_ref(),
DocItem::Member(DocMember::Property(p)) => p.docs.as_ref(),
}
}
pub fn get_doc_summary(&self) -> Option<&str> {
self.get_doc_string().map(|ds| ds.summary.as_str())
}
pub fn try_as_member_with_collapsed_object(&self) -> Result<DocMember, &DocModule> {
match self {
DocItem::Module(m) => Err(m),
DocItem::Member(m) => Ok(m.clone()),
DocItem::Type(o) => Ok(DocMember::Property(DocProperty {
docs: o.docs.clone(),
typ: o.ty.clone(),
})),
}
}
pub fn try_as_member(&self) -> Option<DocMember> {
match self {
DocItem::Member(m) => Some(m.clone()),
_ => None,
}
}
}
impl DocMember {
pub fn get_doc_string(&self) -> Option<&DocString> {
match self {
DocMember::Function(f) => f.docs.as_ref(),
DocMember::Property(p) => p.docs.as_ref(),
}
}
pub fn get_doc_summary(&self) -> Option<&str> {
self.get_doc_string().map(|ds| ds.summary.as_str())
}
}
impl DocParam {
pub fn get_doc_string(&self) -> Option<&DocString> {
self.docs.as_ref()
}
pub fn get_doc_summary(&self) -> Option<&str> {
self.get_doc_string().map(|ds| ds.summary.as_str())
}
}