@@ -9,7 +9,6 @@ use rustc_middle::middle::stability;
99use rustc_middle:: ty:: { self , TyCtxt } ;
1010use rustc_span:: hygiene:: MacroKind ;
1111use rustc_span:: symbol:: { kw, sym, Symbol } ;
12- use std:: borrow:: Borrow ;
1312use std:: cell:: { RefCell , RefMut } ;
1413use std:: cmp:: Ordering ;
1514use std:: fmt;
@@ -40,6 +39,110 @@ use crate::html::{highlight, static_files};
4039use askama:: Template ;
4140use itertools:: Itertools ;
4241
42+ /// Generates an Askama template struct for rendering items with common methods.
43+ ///
44+ /// Usage:
45+ /// ```ignore (illustrative)
46+ /// item_template!(
47+ /// #[template(path = "<template.html>", /* additional values */)]
48+ /// /* additional meta items */
49+ /// struct MyItem<'a, 'cx> {
50+ /// cx: RefCell<&'a mut Context<'cx>>,
51+ /// it: &'a clean::Item,
52+ /// /* additional fields */
53+ /// },
54+ /// methods = [ /* method names (comma separated; refer to macro definition of `item_template_methods!()`) */ ]
55+ /// )
56+ /// ```
57+ ///
58+ /// NOTE: ensure that the generic lifetimes (`'a`, `'cx`) and
59+ /// required fields (`cx`, `it`) are identical (in terms of order and definition).
60+ macro_rules! item_template {
61+ (
62+ $( #[ $meta: meta] ) *
63+ struct $name: ident<' a, ' cx> {
64+ cx: RefCell <& ' a mut Context <' cx>>,
65+ it: & ' a clean:: Item ,
66+ $( $field_name: ident: $field_ty: ty) ,* ,
67+ } ,
68+ methods = [ $( $methods: tt) ,* $( , ) ?]
69+ ) => {
70+ #[ derive( Template ) ]
71+ $( #[ $meta] ) *
72+ struct $name<' a, ' cx> {
73+ cx: RefCell <& ' a mut Context <' cx>>,
74+ it: & ' a clean:: Item ,
75+ $( $field_name: $field_ty) ,*
76+ }
77+
78+ impl <' a, ' cx: ' a> ItemTemplate <' a, ' cx> for $name<' a, ' cx> {
79+ fn item_and_mut_cx( & self ) -> ( & ' a clean:: Item , RefMut <' _, & ' a mut Context <' cx>>) {
80+ ( & self . it, self . cx. borrow_mut( ) )
81+ }
82+ }
83+
84+ impl <' a, ' cx: ' a> $name<' a, ' cx> {
85+ item_template_methods!( $( $methods) * ) ;
86+ }
87+ } ;
88+ }
89+
90+ /// Implement common methods for item template structs generated by `item_template!()`.
91+ ///
92+ /// NOTE: this macro is intended to be used only by `item_template!()`.
93+ macro_rules! item_template_methods {
94+ ( ) => { } ;
95+ ( document $( $rest: tt) * ) => {
96+ fn document<' b>( & ' b self ) -> impl fmt:: Display + Captures <' a> + ' b + Captures <' cx> {
97+ display_fn( move |f| {
98+ let ( item, mut cx) = self . item_and_mut_cx( ) ;
99+ let v = document( * cx, item, None , HeadingOffset :: H2 ) ;
100+ write!( f, "{v}" )
101+ } )
102+ }
103+ item_template_methods!( $( $rest) * ) ;
104+ } ;
105+ ( document_type_layout $( $rest: tt) * ) => {
106+ fn document_type_layout<' b>( & ' b self ) -> impl fmt:: Display + Captures <' a> + ' b + Captures <' cx> {
107+ display_fn( move |f| {
108+ let ( item, cx) = self . item_and_mut_cx( ) ;
109+ let def_id = item. item_id. expect_def_id( ) ;
110+ let v = document_type_layout( * cx, def_id) ;
111+ write!( f, "{v}" )
112+ } )
113+ }
114+ item_template_methods!( $( $rest) * ) ;
115+ } ;
116+ ( render_attributes_in_pre $( $rest: tt) * ) => {
117+ fn render_attributes_in_pre<' b>( & ' b self ) -> impl fmt:: Display + Captures <' a> + ' b + Captures <' cx> {
118+ display_fn( move |f| {
119+ let ( item, cx) = self . item_and_mut_cx( ) ;
120+ let tcx = cx. tcx( ) ;
121+ let v = render_attributes_in_pre( item, "" , tcx) ;
122+ write!( f, "{v}" )
123+ } )
124+ }
125+ item_template_methods!( $( $rest) * ) ;
126+ } ;
127+ ( render_assoc_items $( $rest: tt) * ) => {
128+ fn render_assoc_items<' b>( & ' b self ) -> impl fmt:: Display + Captures <' a> + ' b + Captures <' cx> {
129+ display_fn( move |f| {
130+ let ( item, mut cx) = self . item_and_mut_cx( ) ;
131+ let def_id = item. item_id. expect_def_id( ) ;
132+ let v = render_assoc_items( * cx, item, def_id, AssocItemRender :: All , None ) ;
133+ write!( f, "{v}" )
134+ } )
135+ }
136+ item_template_methods!( $( $rest) * ) ;
137+ } ;
138+ ( $method: ident $( $rest: tt) * ) => {
139+ compile_error!( concat!( "unknown method: " , stringify!( $method) ) ) ;
140+ } ;
141+ ( $token: tt $( $rest: tt) * ) => {
142+ compile_error!( concat!( "unexpected token: " , stringify!( $token) ) ) ;
143+ } ;
144+ }
145+
43146const ITEM_TABLE_OPEN : & str = "<ul class=\" item-table\" >" ;
44147const ITEM_TABLE_CLOSE : & str = "</ul>" ;
45148const ITEM_TABLE_ROW_OPEN : & str = "<li>" ;
@@ -222,49 +325,6 @@ trait ItemTemplate<'a, 'cx: 'a>: askama::Template + fmt::Display {
222325 fn item_and_mut_cx ( & self ) -> ( & ' a clean:: Item , RefMut < ' _ , & ' a mut Context < ' cx > > ) ;
223326}
224327
225- fn item_template_document < ' a : ' b , ' b , ' cx : ' a > (
226- templ : & ' b impl ItemTemplate < ' a , ' cx > ,
227- ) -> impl fmt:: Display + Captures < ' a > + ' b + Captures < ' cx > {
228- display_fn ( move |f| {
229- let ( item, mut cx) = templ. item_and_mut_cx ( ) ;
230- let v = document ( * cx, item, None , HeadingOffset :: H2 ) ;
231- write ! ( f, "{v}" )
232- } )
233- }
234-
235- fn item_template_document_type_layout < ' a : ' b , ' b , ' cx : ' a > (
236- templ : & ' b impl ItemTemplate < ' a , ' cx > ,
237- ) -> impl fmt:: Display + Captures < ' a > + ' b + Captures < ' cx > {
238- display_fn ( move |f| {
239- let ( item, cx) = templ. item_and_mut_cx ( ) ;
240- let def_id = item. item_id . expect_def_id ( ) ;
241- let v = document_type_layout ( * cx, def_id) ;
242- write ! ( f, "{v}" )
243- } )
244- }
245-
246- fn item_template_render_attributes_in_pre < ' a : ' b , ' b , ' cx : ' a > (
247- templ : & ' b impl ItemTemplate < ' a , ' cx > ,
248- ) -> impl fmt:: Display + Captures < ' a > + ' b + Captures < ' cx > {
249- display_fn ( move |f| {
250- let ( item, cx) = templ. item_and_mut_cx ( ) ;
251- let tcx = cx. tcx ( ) ;
252- let v = render_attributes_in_pre ( item, "" , tcx) ;
253- write ! ( f, "{v}" )
254- } )
255- }
256-
257- fn item_template_render_assoc_items < ' a : ' b , ' b , ' cx : ' a > (
258- templ : & ' b impl ItemTemplate < ' a , ' cx > ,
259- ) -> impl fmt:: Display + Captures < ' a > + ' b + Captures < ' cx > {
260- display_fn ( move |f| {
261- let ( item, mut cx) = templ. item_and_mut_cx ( ) ;
262- let def_id = item. item_id . expect_def_id ( ) ;
263- let v = render_assoc_items ( * cx, item, def_id, AssocItemRender :: All , None ) ;
264- write ! ( f, "{v}" )
265- } )
266- }
267-
268328fn item_module ( w : & mut Buffer , cx : & mut Context < ' _ > , item : & clean:: Item , items : & [ clean:: Item ] ) {
269329 write ! ( w, "{}" , document( cx, item, None , HeadingOffset :: H2 ) ) ;
270330
@@ -1200,19 +1260,15 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea
12001260}
12011261
12021262fn item_union ( w : & mut Buffer , cx : & mut Context < ' _ > , it : & clean:: Item , s : & clean:: Union ) {
1203- #[ derive( Template ) ]
1204- #[ template( path = "item_union.html" ) ]
1205- struct ItemUnion < ' a , ' cx > {
1206- cx : RefCell < & ' a mut Context < ' cx > > ,
1207- it : & ' a clean:: Item ,
1208- s : & ' a clean:: Union ,
1209- }
1210-
1211- impl < ' a , ' cx : ' a > ItemTemplate < ' a , ' cx > for ItemUnion < ' a , ' cx > {
1212- fn item_and_mut_cx ( & self ) -> ( & ' a clean:: Item , RefMut < ' _ , & ' a mut Context < ' cx > > ) {
1213- ( self . it , self . cx . borrow_mut ( ) )
1214- }
1215- }
1263+ item_template ! (
1264+ #[ template( path = "item_union.html" ) ]
1265+ struct ItemUnion <' a, ' cx> {
1266+ cx: RefCell <& ' a mut Context <' cx>>,
1267+ it: & ' a clean:: Item ,
1268+ s: & ' a clean:: Union ,
1269+ } ,
1270+ methods = [ document, document_type_layout, render_attributes_in_pre, render_assoc_items]
1271+ ) ;
12161272
12171273 impl < ' a , ' cx : ' a > ItemUnion < ' a , ' cx > {
12181274 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:
12221278 write ! ( f, "{v}" )
12231279 } )
12241280 }
1281+
12251282 fn document_field < ' b > (
12261283 & ' b self ,
12271284 field : & ' a clean:: Item ,
@@ -1232,10 +1289,12 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
12321289 write ! ( f, "{v}" )
12331290 } )
12341291 }
1292+
12351293 fn stability_field ( & self , field : & clean:: Item ) -> Option < String > {
12361294 let cx = self . cx . borrow ( ) ;
12371295 field. stability_class ( cx. tcx ( ) )
12381296 }
1297+
12391298 fn print_ty < ' b > (
12401299 & ' b self ,
12411300 ty : & ' a clean:: Type ,
0 commit comments