Add item_template
macro
This commit is contained in:
parent
4b71d79c97
commit
e240dab0c8
@ -9,7 +9,6 @@ use rustc_middle::middle::stability;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use std::borrow::Borrow;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
@ -40,6 +39,110 @@ use crate::html::{highlight, static_files};
|
||||
use askama::Template;
|
||||
use itertools::Itertools;
|
||||
|
||||
/// Generates an Askama template struct for rendering items with common methods.
|
||||
///
|
||||
/// Usage:
|
||||
/// ```ignore (illustrative)
|
||||
/// item_template!(
|
||||
/// #[template(path = "<template.html>", /* additional values */)]
|
||||
/// /* additional meta items */
|
||||
/// struct MyItem<'a, 'cx> {
|
||||
/// cx: RefCell<&'a mut Context<'cx>>,
|
||||
/// it: &'a clean::Item,
|
||||
/// /* additional fields */
|
||||
/// },
|
||||
/// methods = [ /* method names (comma separated; refer to macro definition of `item_template_methods!()`) */ ]
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// NOTE: ensure that the generic lifetimes (`'a`, `'cx`) and
|
||||
/// required fields (`cx`, `it`) are identical (in terms of order and definition).
|
||||
macro_rules! item_template {
|
||||
(
|
||||
$(#[$meta:meta])*
|
||||
struct $name:ident<'a, 'cx> {
|
||||
cx: RefCell<&'a mut Context<'cx>>,
|
||||
it: &'a clean::Item,
|
||||
$($field_name:ident: $field_ty:ty),*,
|
||||
},
|
||||
methods = [$($methods:tt),* $(,)?]
|
||||
) => {
|
||||
#[derive(Template)]
|
||||
$(#[$meta])*
|
||||
struct $name<'a, 'cx> {
|
||||
cx: RefCell<&'a mut Context<'cx>>,
|
||||
it: &'a clean::Item,
|
||||
$($field_name: $field_ty),*
|
||||
}
|
||||
|
||||
impl<'a, 'cx: 'a> ItemTemplate<'a, 'cx> for $name<'a, 'cx> {
|
||||
fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>) {
|
||||
(&self.it, self.cx.borrow_mut())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'cx: 'a> $name<'a, 'cx> {
|
||||
item_template_methods!($($methods)*);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Implement common methods for item template structs generated by `item_template!()`.
|
||||
///
|
||||
/// NOTE: this macro is intended to be used only by `item_template!()`.
|
||||
macro_rules! item_template_methods {
|
||||
() => {};
|
||||
(document $($rest:tt)*) => {
|
||||
fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
let (item, mut cx) = self.item_and_mut_cx();
|
||||
let v = document(*cx, item, None, HeadingOffset::H2);
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
item_template_methods!($($rest)*);
|
||||
};
|
||||
(document_type_layout $($rest:tt)*) => {
|
||||
fn document_type_layout<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
let (item, cx) = self.item_and_mut_cx();
|
||||
let def_id = item.item_id.expect_def_id();
|
||||
let v = document_type_layout(*cx, def_id);
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
item_template_methods!($($rest)*);
|
||||
};
|
||||
(render_attributes_in_pre $($rest:tt)*) => {
|
||||
fn render_attributes_in_pre<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
let (item, cx) = self.item_and_mut_cx();
|
||||
let tcx = cx.tcx();
|
||||
let v = render_attributes_in_pre(item, "", tcx);
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
item_template_methods!($($rest)*);
|
||||
};
|
||||
(render_assoc_items $($rest:tt)*) => {
|
||||
fn render_assoc_items<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
let (item, mut cx) = self.item_and_mut_cx();
|
||||
let def_id = item.item_id.expect_def_id();
|
||||
let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All, None);
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
item_template_methods!($($rest)*);
|
||||
};
|
||||
($method:ident $($rest:tt)*) => {
|
||||
compile_error!(concat!("unknown method: ", stringify!($method)));
|
||||
};
|
||||
($token:tt $($rest:tt)*) => {
|
||||
compile_error!(concat!("unexpected token: ", stringify!($token)));
|
||||
};
|
||||
}
|
||||
|
||||
const ITEM_TABLE_OPEN: &str = "<ul class=\"item-table\">";
|
||||
const ITEM_TABLE_CLOSE: &str = "</ul>";
|
||||
const ITEM_TABLE_ROW_OPEN: &str = "<li>";
|
||||
@ -222,49 +325,6 @@ trait ItemTemplate<'a, 'cx: 'a>: askama::Template + fmt::Display {
|
||||
fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>);
|
||||
}
|
||||
|
||||
fn item_template_document<'a: 'b, 'b, 'cx: 'a>(
|
||||
templ: &'b impl ItemTemplate<'a, 'cx>,
|
||||
) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
let (item, mut cx) = templ.item_and_mut_cx();
|
||||
let v = document(*cx, item, None, HeadingOffset::H2);
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
|
||||
fn item_template_document_type_layout<'a: 'b, 'b, 'cx: 'a>(
|
||||
templ: &'b impl ItemTemplate<'a, 'cx>,
|
||||
) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
let (item, cx) = templ.item_and_mut_cx();
|
||||
let def_id = item.item_id.expect_def_id();
|
||||
let v = document_type_layout(*cx, def_id);
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
|
||||
fn item_template_render_attributes_in_pre<'a: 'b, 'b, 'cx: 'a>(
|
||||
templ: &'b impl ItemTemplate<'a, 'cx>,
|
||||
) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
let (item, cx) = templ.item_and_mut_cx();
|
||||
let tcx = cx.tcx();
|
||||
let v = render_attributes_in_pre(item, "", tcx);
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
|
||||
fn item_template_render_assoc_items<'a: 'b, 'b, 'cx: 'a>(
|
||||
templ: &'b impl ItemTemplate<'a, 'cx>,
|
||||
) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
let (item, mut cx) = templ.item_and_mut_cx();
|
||||
let def_id = item.item_id.expect_def_id();
|
||||
let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All, None);
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
|
||||
fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) {
|
||||
write!(w, "{}", document(cx, item, None, HeadingOffset::H2));
|
||||
|
||||
@ -1200,19 +1260,15 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea
|
||||
}
|
||||
|
||||
fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) {
|
||||
#[derive(Template)]
|
||||
#[template(path = "item_union.html")]
|
||||
struct ItemUnion<'a, 'cx> {
|
||||
cx: RefCell<&'a mut Context<'cx>>,
|
||||
it: &'a clean::Item,
|
||||
s: &'a clean::Union,
|
||||
}
|
||||
|
||||
impl<'a, 'cx: 'a> ItemTemplate<'a, 'cx> for ItemUnion<'a, 'cx> {
|
||||
fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>) {
|
||||
(self.it, self.cx.borrow_mut())
|
||||
}
|
||||
}
|
||||
item_template!(
|
||||
#[template(path = "item_union.html")]
|
||||
struct ItemUnion<'a, 'cx> {
|
||||
cx: RefCell<&'a mut Context<'cx>>,
|
||||
it: &'a clean::Item,
|
||||
s: &'a clean::Union,
|
||||
},
|
||||
methods = [document, document_type_layout, render_attributes_in_pre, render_assoc_items]
|
||||
);
|
||||
|
||||
impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
|
||||
fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
@ -1222,6 +1278,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
|
||||
fn document_field<'b>(
|
||||
&'b self,
|
||||
field: &'a clean::Item,
|
||||
@ -1232,10 +1289,12 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
|
||||
fn stability_field(&self, field: &clean::Item) -> Option<String> {
|
||||
let cx = self.cx.borrow();
|
||||
field.stability_class(cx.tcx())
|
||||
}
|
||||
|
||||
fn print_ty<'b>(
|
||||
&'b self,
|
||||
ty: &'a clean::Type,
|
||||
|
@ -1,8 +1,8 @@
|
||||
<pre class="rust item-decl"><code>
|
||||
{{ self::item_template_render_attributes_in_pre(self.borrow()) | safe }}
|
||||
{{ self.render_attributes_in_pre() | safe }}
|
||||
{{ self.render_union() | safe }}
|
||||
</code></pre>
|
||||
{{ self::item_template_document(self.borrow()) | safe }}
|
||||
{{ self.document() | safe }}
|
||||
{% if self.fields_iter().peek().is_some() %}
|
||||
<h2 id="fields" class="fields small-section-header">
|
||||
Fields<a href="#fields" class="anchor">§</a>
|
||||
@ -19,5 +19,5 @@
|
||||
{{ self.document_field(field) | safe }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{{ self::item_template_render_assoc_items(self.borrow()) | safe }}
|
||||
{{ self::item_template_document_type_layout(self.borrow()) | safe }}
|
||||
{{ self.render_assoc_items() | safe }}
|
||||
{{ self.document_type_layout() | safe }}
|
||||
|
Loading…
x
Reference in New Issue
Block a user