Support data-types in documentation.
This commit is contained in:
parent
1f3f769b53
commit
d2c6d27545
|
@ -130,14 +130,14 @@ impl TypedDataType {
|
||||||
tipo: tipo.clone(),
|
tipo: tipo.clone(),
|
||||||
doc: None,
|
doc: None,
|
||||||
}],
|
}],
|
||||||
documentation: None,
|
doc: None,
|
||||||
sugar: false,
|
sugar: false,
|
||||||
},
|
},
|
||||||
RecordConstructor {
|
RecordConstructor {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
name: "None".to_string(),
|
name: "None".to_string(),
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
documentation: None,
|
doc: None,
|
||||||
sugar: false,
|
sugar: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -352,7 +352,7 @@ pub struct RecordConstructor<T> {
|
||||||
pub location: Span,
|
pub location: Span,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub arguments: Vec<RecordConstructorArg<T>>,
|
pub arguments: Vec<RecordConstructorArg<T>>,
|
||||||
pub documentation: Option<String>,
|
pub doc: Option<String>,
|
||||||
pub sugar: bool,
|
pub sugar: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1172,37 +1172,93 @@ impl<'comments> Formatter<'comments> {
|
||||||
.append("}")
|
.append("}")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn docs_opaque_custom_type<'a>(
|
pub fn docs_data_type<'a, A>(
|
||||||
|
&mut self,
|
||||||
|
name: &'a str,
|
||||||
|
args: &'a [String],
|
||||||
|
constructors: &'a [RecordConstructor<A>],
|
||||||
|
location: &'a Span,
|
||||||
|
) -> Document<'a> {
|
||||||
|
self.pop_empty_lines(location.start);
|
||||||
|
|
||||||
|
let mut is_sugar = false;
|
||||||
|
|
||||||
|
(if args.is_empty() {
|
||||||
|
name.to_doc()
|
||||||
|
} else {
|
||||||
|
name.to_doc()
|
||||||
|
.append(wrap_generics(args.iter().map(|e| e.to_doc())))
|
||||||
|
.group()
|
||||||
|
})
|
||||||
|
.append(" {")
|
||||||
|
.append(if constructors.len() == 1 && constructors[0].sugar {
|
||||||
|
is_sugar = true;
|
||||||
|
|
||||||
|
self.record_constructor(&constructors[0])
|
||||||
|
} else {
|
||||||
|
concat(constructors.iter().map(|c| {
|
||||||
|
if self.pop_empty_lines(c.location.start) {
|
||||||
|
lines(2)
|
||||||
|
} else {
|
||||||
|
line()
|
||||||
|
}
|
||||||
|
.append(self.record_constructor(c))
|
||||||
|
.nest(INDENT)
|
||||||
|
.group()
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
.append(if is_sugar { nil() } else { line() })
|
||||||
|
.append("}")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn docs_opaque_data_type<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
public: bool,
|
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
args: &'a [String],
|
args: &'a [String],
|
||||||
location: &'a Span,
|
location: &'a Span,
|
||||||
) -> Document<'a> {
|
) -> Document<'a> {
|
||||||
self.pop_empty_lines(location.start);
|
self.pop_empty_lines(location.start);
|
||||||
pub_(public)
|
if args.is_empty() {
|
||||||
.to_doc()
|
|
||||||
.append("opaque type ")
|
|
||||||
.append(if args.is_empty() {
|
|
||||||
name.to_doc()
|
name.to_doc()
|
||||||
} else {
|
} else {
|
||||||
name.to_doc()
|
name.to_doc()
|
||||||
.append(wrap_args(args.iter().map(|e| (e.to_doc(), false))))
|
.append(wrap_args(args.iter().map(|e| (e.to_doc(), false))))
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn docs_type_alias<'a>(
|
||||||
|
&mut self,
|
||||||
|
name: &'a str,
|
||||||
|
args: &'a [String],
|
||||||
|
typ: &'a Annotation,
|
||||||
|
) -> Document<'a> {
|
||||||
|
let head = name.to_doc();
|
||||||
|
|
||||||
|
let head = if args.is_empty() {
|
||||||
|
head
|
||||||
|
} else {
|
||||||
|
head.append(wrap_generics(args.iter().map(|e| e.to_doc())).group())
|
||||||
|
};
|
||||||
|
|
||||||
|
head.append(" = ")
|
||||||
|
.append(self.annotation(typ).group().nest(INDENT))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn docs_record_constructor<'a, A>(
|
||||||
|
&mut self,
|
||||||
|
constructor: &'a RecordConstructor<A>,
|
||||||
|
) -> Document<'a> {
|
||||||
|
constructor.name.to_doc()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn docs_fn_signature<'a>(
|
pub fn docs_fn_signature<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
public: bool,
|
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
args: &'a [TypedArg],
|
args: &'a [TypedArg],
|
||||||
return_type: Arc<Type>,
|
return_type: Arc<Type>,
|
||||||
) -> Document<'a> {
|
) -> Document<'a> {
|
||||||
let mut printer = tipo::pretty::Printer::new();
|
let mut printer = tipo::pretty::Printer::new();
|
||||||
|
name.to_doc()
|
||||||
pub_(public)
|
|
||||||
.append("fn ")
|
|
||||||
.append(name)
|
|
||||||
.append(self.docs_fn_args(args, &mut printer))
|
.append(self.docs_fn_args(args, &mut printer))
|
||||||
.append(" -> ".to_doc())
|
.append(" -> ".to_doc())
|
||||||
.append(printer.print(&return_type))
|
.append(printer.print(&return_type))
|
||||||
|
|
|
@ -157,7 +157,7 @@ pub fn data_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = Parse
|
||||||
location: span,
|
location: span,
|
||||||
arguments: arguments.unwrap_or_default(),
|
arguments: arguments.unwrap_or_default(),
|
||||||
name,
|
name,
|
||||||
documentation: None,
|
doc: None,
|
||||||
sugar: false,
|
sugar: false,
|
||||||
})
|
})
|
||||||
.repeated()
|
.repeated()
|
||||||
|
@ -167,7 +167,7 @@ pub fn data_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = Parse
|
||||||
vec![ast::RecordConstructor {
|
vec![ast::RecordConstructor {
|
||||||
location: span,
|
location: span,
|
||||||
arguments,
|
arguments,
|
||||||
documentation: None,
|
doc: None,
|
||||||
name: String::from("_replace"),
|
name: String::from("_replace"),
|
||||||
sugar: true,
|
sugar: true,
|
||||||
}]
|
}]
|
||||||
|
|
|
@ -130,14 +130,14 @@ fn custom_type() {
|
||||||
doc: None,
|
doc: None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
documentation: None,
|
doc: None,
|
||||||
sugar: false,
|
sugar: false,
|
||||||
},
|
},
|
||||||
ast::RecordConstructor {
|
ast::RecordConstructor {
|
||||||
location: Span::new((), 34..38),
|
location: Span::new((), 34..38),
|
||||||
name: "None".to_string(),
|
name: "None".to_string(),
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
documentation: None,
|
doc: None,
|
||||||
sugar: false,
|
sugar: false,
|
||||||
},
|
},
|
||||||
ast::RecordConstructor {
|
ast::RecordConstructor {
|
||||||
|
@ -169,7 +169,7 @@ fn custom_type() {
|
||||||
doc: None,
|
doc: None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
documentation: None,
|
doc: None,
|
||||||
sugar: false,
|
sugar: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -208,7 +208,7 @@ fn opaque_type() {
|
||||||
tipo: (),
|
tipo: (),
|
||||||
doc: None,
|
doc: None,
|
||||||
}],
|
}],
|
||||||
documentation: None,
|
doc: None,
|
||||||
sugar: true,
|
sugar: true,
|
||||||
}],
|
}],
|
||||||
doc: None,
|
doc: None,
|
||||||
|
|
|
@ -288,7 +288,7 @@ fn infer_definition(
|
||||||
location,
|
location,
|
||||||
name,
|
name,
|
||||||
arguments: args,
|
arguments: args,
|
||||||
documentation,
|
doc,
|
||||||
sugar,
|
sugar,
|
||||||
}| {
|
}| {
|
||||||
let preregistered_fn = environment
|
let preregistered_fn = environment
|
||||||
|
@ -330,7 +330,7 @@ fn infer_definition(
|
||||||
location,
|
location,
|
||||||
name,
|
name,
|
||||||
arguments: args,
|
arguments: args,
|
||||||
documentation,
|
doc,
|
||||||
sugar,
|
sugar,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::{config::Config, module::CheckedModule};
|
use crate::{config::Config, module::CheckedModule};
|
||||||
use aiken_lang::{
|
use aiken_lang::{
|
||||||
ast::{Definition, TypedDefinition},
|
ast::{Definition, RecordConstructor, RecordConstructorArg, TypedDefinition},
|
||||||
format,
|
format,
|
||||||
|
tipo::Type,
|
||||||
};
|
};
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -10,6 +11,7 @@ use serde::Serialize;
|
||||||
use serde_json as json;
|
use serde_json as json;
|
||||||
use std::{
|
use std::{
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
|
sync::Arc,
|
||||||
time::{Duration, SystemTime},
|
time::{Duration, SystemTime},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -75,24 +77,26 @@ struct SearchIndex {
|
||||||
/// across multiple modules.
|
/// across multiple modules.
|
||||||
pub fn generate_all(root: &PathBuf, config: &Config, modules: Vec<&CheckedModule>) -> Vec<DocFile> {
|
pub fn generate_all(root: &PathBuf, config: &Config, modules: Vec<&CheckedModule>) -> Vec<DocFile> {
|
||||||
let timestamp = new_timestamp();
|
let timestamp = new_timestamp();
|
||||||
|
let modules_links = generate_modules_links(&modules);
|
||||||
|
|
||||||
let mut output_files: Vec<DocFile> = vec![];
|
let mut output_files: Vec<DocFile> = vec![];
|
||||||
let mut search_indexes: Vec<SearchIndex> = vec![];
|
let mut search_indexes: Vec<SearchIndex> = vec![];
|
||||||
|
|
||||||
for module in &modules {
|
for module in &modules {
|
||||||
let (indexes, file) = generate_module(config, module, ×tamp);
|
let (indexes, file) = generate_module(config, module, &modules_links, ×tamp);
|
||||||
search_indexes.extend(indexes);
|
search_indexes.extend(indexes);
|
||||||
output_files.push(file);
|
output_files.push(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
output_files.extend(generate_static_assets(search_indexes));
|
output_files.extend(generate_static_assets(search_indexes));
|
||||||
output_files.push(generate_readme(root, config, modules, ×tamp));
|
output_files.push(generate_readme(root, config, &modules_links, ×tamp));
|
||||||
output_files
|
output_files
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_module(
|
fn generate_module(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
module: &CheckedModule,
|
module: &CheckedModule,
|
||||||
|
modules: &Vec<DocLink>,
|
||||||
timestamp: &Duration,
|
timestamp: &Duration,
|
||||||
) -> (Vec<SearchIndex>, DocFile) {
|
) -> (Vec<SearchIndex>, DocFile) {
|
||||||
let mut search_indexes = vec![];
|
let mut search_indexes = vec![];
|
||||||
|
@ -116,11 +120,44 @@ fn generate_module(
|
||||||
});
|
});
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
|
let types: Vec<DocType> = module
|
||||||
|
.ast
|
||||||
|
.definitions
|
||||||
|
.iter()
|
||||||
|
.flat_map(DocType::from_definition)
|
||||||
|
.sorted()
|
||||||
|
.collect();
|
||||||
|
types.iter().for_each(|type_info| {
|
||||||
|
let constructors = type_info
|
||||||
|
.constructors
|
||||||
|
.iter()
|
||||||
|
.map(|constructor| {
|
||||||
|
let arguments = constructor
|
||||||
|
.arguments
|
||||||
|
.iter()
|
||||||
|
.map(|argument| format!("{}\n{}", argument.label, argument.documentation))
|
||||||
|
.join("\n");
|
||||||
|
format!(
|
||||||
|
"{}\n{}\n{}",
|
||||||
|
constructor.definition, constructor.documentation, arguments
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.join("\n");
|
||||||
|
search_indexes.push(SearchIndex {
|
||||||
|
doc: module.name.to_string(),
|
||||||
|
title: type_info.name.to_string(),
|
||||||
|
content: format!(
|
||||||
|
"{}\n{}\n{}",
|
||||||
|
type_info.definition, type_info.documentation, constructors,
|
||||||
|
),
|
||||||
|
url: format!("{}.html#{}", module.name, type_info.name),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
|
// TODO
|
||||||
|
|
||||||
// Template
|
// Module
|
||||||
|
|
||||||
search_indexes.push(SearchIndex {
|
search_indexes.push(SearchIndex {
|
||||||
doc: module.name.to_string(),
|
doc: module.name.to_string(),
|
||||||
title: module.name.to_string(),
|
title: module.name.to_string(),
|
||||||
|
@ -133,13 +170,13 @@ fn generate_module(
|
||||||
breadcrumbs: to_breadcrumbs(&module.name),
|
breadcrumbs: to_breadcrumbs(&module.name),
|
||||||
links: &vec![],
|
links: &vec![],
|
||||||
documentation: render_markdown(&module.ast.docs.iter().join("\n")),
|
documentation: render_markdown(&module.ast.docs.iter().join("\n")),
|
||||||
modules: &vec![],
|
modules,
|
||||||
project_name: &config.name,
|
project_name: &config.name,
|
||||||
page_title: &format!("{} - {}", module.name, config.name),
|
page_title: &format!("{} - {}", module.name, config.name),
|
||||||
module_name: module.name.clone(),
|
module_name: module.name.clone(),
|
||||||
project_version: &config.version.to_string(),
|
project_version: &config.version.to_string(),
|
||||||
functions,
|
functions,
|
||||||
types: vec![],
|
types,
|
||||||
constants: vec![],
|
constants: vec![],
|
||||||
timestamp: timestamp.as_secs().to_string(),
|
timestamp: timestamp.as_secs().to_string(),
|
||||||
};
|
};
|
||||||
|
@ -208,28 +245,18 @@ fn generate_static_assets(search_indexes: Vec<SearchIndex>) -> Vec<DocFile> {
|
||||||
fn generate_readme(
|
fn generate_readme(
|
||||||
root: &PathBuf,
|
root: &PathBuf,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
modules: Vec<&CheckedModule>,
|
modules: &Vec<DocLink>,
|
||||||
timestamp: &Duration,
|
timestamp: &Duration,
|
||||||
) -> DocFile {
|
) -> DocFile {
|
||||||
let path = PathBuf::from("index.html");
|
let path = PathBuf::from("index.html");
|
||||||
|
|
||||||
let content = std::fs::read_to_string(root.join("README.md")).unwrap_or_default();
|
let content = std::fs::read_to_string(root.join("README.md")).unwrap_or_default();
|
||||||
|
|
||||||
let mut modules_links = vec![];
|
|
||||||
for module in modules {
|
|
||||||
let module_path = [&module.name.clone(), ".html"].concat();
|
|
||||||
modules_links.push(DocLink {
|
|
||||||
path: module_path,
|
|
||||||
name: module.name.to_string().clone(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
modules_links.sort();
|
|
||||||
|
|
||||||
let template = PageTemplate {
|
let template = PageTemplate {
|
||||||
aiken_version: VERSION,
|
aiken_version: VERSION,
|
||||||
breadcrumbs: ".",
|
breadcrumbs: ".",
|
||||||
links: &vec![],
|
links: &vec![],
|
||||||
modules: &modules_links,
|
modules,
|
||||||
project_name: &config.name,
|
project_name: &config.name,
|
||||||
page_title: &config.name,
|
page_title: &config.name,
|
||||||
project_version: &config.version.to_string(),
|
project_version: &config.version.to_string(),
|
||||||
|
@ -243,6 +270,19 @@ fn generate_readme(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_modules_links(modules: &Vec<&CheckedModule>) -> Vec<DocLink> {
|
||||||
|
let mut modules_links = vec![];
|
||||||
|
for module in modules {
|
||||||
|
let module_path = [&module.name.clone(), ".html"].concat();
|
||||||
|
modules_links.push(DocLink {
|
||||||
|
path: module_path,
|
||||||
|
name: module.name.to_string().clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
modules_links.sort();
|
||||||
|
modules_links
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||||
struct DocFunction {
|
struct DocFunction {
|
||||||
name: String,
|
name: String,
|
||||||
|
@ -263,13 +303,12 @@ impl DocFunction {
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
signature: format::Formatter::new()
|
signature: format::Formatter::new()
|
||||||
.docs_fn_signature(
|
.docs_fn_signature(
|
||||||
true,
|
|
||||||
&func_def.name,
|
&func_def.name,
|
||||||
&func_def.arguments,
|
&func_def.arguments,
|
||||||
func_def.return_type.clone(),
|
func_def.return_type.clone(),
|
||||||
)
|
)
|
||||||
.to_pretty_string(MAX_COLUMNS),
|
.to_pretty_string(MAX_COLUMNS),
|
||||||
source_url: "TODO: source_url".to_string(),
|
source_url: "#todo".to_string(),
|
||||||
}),
|
}),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -281,7 +320,6 @@ struct DocConstant {
|
||||||
name: String,
|
name: String,
|
||||||
definition: String,
|
definition: String,
|
||||||
documentation: String,
|
documentation: String,
|
||||||
text_documentation: String,
|
|
||||||
source_url: String,
|
source_url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,22 +329,99 @@ struct DocType {
|
||||||
definition: String,
|
definition: String,
|
||||||
documentation: String,
|
documentation: String,
|
||||||
constructors: Vec<DocTypeConstructor>,
|
constructors: Vec<DocTypeConstructor>,
|
||||||
text_documentation: String,
|
|
||||||
source_url: String,
|
source_url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DocType {
|
||||||
|
fn from_definition(def: &TypedDefinition) -> Option<Self> {
|
||||||
|
match def {
|
||||||
|
Definition::TypeAlias(info) if info.public => Some(DocType {
|
||||||
|
name: info.alias.clone(),
|
||||||
|
definition: format::Formatter::new()
|
||||||
|
.docs_type_alias(&info.alias, &info.parameters, &info.annotation)
|
||||||
|
.to_pretty_string(MAX_COLUMNS),
|
||||||
|
documentation: info.doc.as_deref().map(render_markdown).unwrap_or_default(),
|
||||||
|
constructors: vec![],
|
||||||
|
source_url: "#todo".to_string(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
Definition::DataType(info) if info.public && !info.opaque => Some(DocType {
|
||||||
|
name: info.name.clone(),
|
||||||
|
definition: format::Formatter::new()
|
||||||
|
.docs_data_type(
|
||||||
|
&info.name,
|
||||||
|
&info.parameters,
|
||||||
|
&info.constructors,
|
||||||
|
&info.location,
|
||||||
|
)
|
||||||
|
.to_pretty_string(MAX_COLUMNS),
|
||||||
|
documentation: info.doc.as_deref().map(render_markdown).unwrap_or_default(),
|
||||||
|
constructors: info
|
||||||
|
.constructors
|
||||||
|
.iter()
|
||||||
|
.map(DocTypeConstructor::from_record_constructor)
|
||||||
|
.collect(),
|
||||||
|
source_url: "#todo".to_string(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
Definition::DataType(info) if info.public && info.opaque => Some(DocType {
|
||||||
|
name: info.name.clone(),
|
||||||
|
definition: format::Formatter::new()
|
||||||
|
.docs_opaque_data_type(&info.name, &info.parameters, &info.location)
|
||||||
|
.to_pretty_string(MAX_COLUMNS),
|
||||||
|
documentation: info.doc.as_deref().map(render_markdown).unwrap_or_default(),
|
||||||
|
constructors: vec![],
|
||||||
|
source_url: "#todo".to_string(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||||
struct DocTypeConstructor {
|
struct DocTypeConstructor {
|
||||||
definition: String,
|
definition: String,
|
||||||
documentation: String,
|
documentation: String,
|
||||||
text_documentation: String,
|
|
||||||
arguments: Vec<DocTypeConstructorArg>,
|
arguments: Vec<DocTypeConstructorArg>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DocTypeConstructor {
|
||||||
|
fn from_record_constructor(constructor: &RecordConstructor<Arc<Type>>) -> Self {
|
||||||
|
DocTypeConstructor {
|
||||||
|
definition: format::Formatter::new()
|
||||||
|
.docs_record_constructor(constructor)
|
||||||
|
.to_pretty_string(MAX_COLUMNS),
|
||||||
|
documentation: constructor
|
||||||
|
.doc
|
||||||
|
.as_deref()
|
||||||
|
.map(render_markdown)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
arguments: constructor
|
||||||
|
.arguments
|
||||||
|
.iter()
|
||||||
|
.filter_map(DocTypeConstructorArg::from_record_constructor_arg)
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||||
struct DocTypeConstructorArg {
|
struct DocTypeConstructorArg {
|
||||||
name: String,
|
label: String,
|
||||||
doc: String,
|
documentation: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DocTypeConstructorArg {
|
||||||
|
fn from_record_constructor_arg(arg: &RecordConstructorArg<Arc<Type>>) -> Option<Self> {
|
||||||
|
match &arg.label {
|
||||||
|
None => None,
|
||||||
|
Some(label) => Some(DocTypeConstructorArg {
|
||||||
|
label: label.clone(),
|
||||||
|
documentation: arg.doc.as_deref().map(render_markdown).unwrap_or_default(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------ Extra Helpers
|
// ------ Extra Helpers
|
||||||
|
|
|
@ -83,10 +83,10 @@
|
||||||
<li>
|
<li>
|
||||||
<div class="constructor-argument-item">
|
<div class="constructor-argument-item">
|
||||||
<p class="constructor-argument-label">
|
<p class="constructor-argument-label">
|
||||||
<i>{{ argument.name }}</i>
|
<i>{{ argument.label }}</i>
|
||||||
</p>
|
</p>
|
||||||
<div class="constructor-argument-doc">
|
<div class="constructor-argument-doc">
|
||||||
{{ argument.doc|safe }}
|
{{ argument.documentation|safe }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
Loading…
Reference in New Issue