@@ -2,60 +2,13 @@ use proc_macro2::{TokenStream as TokenStream2, TokenTree as TokenTree2};
22use quote:: quote;
33use syn:: { parse:: ParseStream , Token } ;
44
5- use crate :: {
6- common:: advance_past_punct,
7- parse:: { wrap_syn_group_macro, AlreadyReported , ParseContext , ReportIn as _} ,
8- } ;
5+ use crate :: parse:: { AlreadyReported , ParseContext , ReportIn as _} ;
96
107#[ derive( Debug , Clone ) ]
118struct DefineStyleClass {
129 visibility : syn:: Visibility ,
1310 name : syn:: Ident ,
14- properties : Vec < ( syn:: Ident , syn:: Expr ) > ,
15- }
16-
17- impl DefineStyleClass {
18- fn parse_properties (
19- buffer : ParseStream ,
20- ctx : & mut ParseContext ,
21- result : & mut Vec < ( syn:: Ident , syn:: Expr ) > ,
22- ) -> Result < ( ) , AlreadyReported > {
23- let mut errored = false ;
24-
25- while !buffer. is_empty ( ) {
26- let Ok ( name) = buffer. parse :: < syn:: Ident > ( ) . report_in ( ctx) else {
27- errored = true ;
28- advance_past_punct ( buffer, ';' ) ;
29- continue ;
30- } ;
31-
32- let Ok ( _) = buffer. parse :: < Token ! [ : ] > ( ) . report_in ( ctx) else {
33- errored = true ;
34- advance_past_punct ( buffer, ';' ) ;
35- continue ;
36- } ;
37-
38- let Ok ( value) = buffer. parse :: < syn:: Expr > ( ) . report_in ( ctx) else {
39- errored = true ;
40- advance_past_punct ( buffer, ';' ) ;
41- continue ;
42- } ;
43-
44- result. push ( ( name, value) ) ;
45-
46- if buffer. is_empty ( ) {
47- break ;
48- }
49-
50- errored |= buffer. parse :: < Token ! [ , ] > ( ) . report_in ( ctx) . is_err ( ) ;
51- }
52-
53- if errored {
54- Err ( AlreadyReported )
55- } else {
56- Ok ( ( ) )
57- }
58- }
11+ source : syn:: LitStr ,
5912}
6013
6114#[ derive( Debug , Clone ) ]
@@ -95,24 +48,19 @@ impl DefineStyleInput {
9548 continue ;
9649 } ;
9750
98- let Ok ( ( inner, _) ) =
99- wrap_syn_group_macro ! ( syn:: braced in buffer) . report_in_and_set ( ctx, & mut errored)
51+ let Ok ( source) = buffer
52+ . parse :: < syn:: LitStr > ( )
53+ . report_in_and_set ( ctx, & mut errored)
10054 else {
10155 _ = buffer. parse :: < TokenTree2 > ( ) ;
10256 continue ;
10357 } ;
10458
105- let mut group = DefineStyleClass {
59+ result . classes . push ( DefineStyleClass {
10660 visibility,
10761 name,
108- properties : Vec :: new ( ) ,
109- } ;
110-
111- if let Ok ( ( ) ) = DefineStyleClass :: parse_properties ( & inner, ctx, & mut group. properties ) {
112- result. classes . push ( group) ;
113- } else {
114- errored = true ;
115- }
62+ source,
63+ } ) ;
11664 }
11765
11866 if errored {
@@ -123,8 +71,8 @@ impl DefineStyleInput {
12371 }
12472}
12573
126- fn apply_function_for_class_name ( class : & syn:: Ident ) -> syn:: Ident {
127- syn:: Ident :: new ( & format ! ( "apply_style_ {class}" ) , class. span ( ) )
74+ fn declarations_name_for_class_name ( class : & syn:: Ident ) -> syn:: Ident {
75+ syn:: Ident :: new ( & format ! ( "STYLE_ {class}_DECLARATIONS " ) , class. span ( ) )
12876}
12977
13078pub fn test_define_style ( ts : proc_macro:: TokenStream ) -> proc_macro:: TokenStream {
@@ -139,47 +87,57 @@ pub fn test_define_style(ts: proc_macro::TokenStream) -> proc_macro::TokenStream
13987 let mut result = TokenStream2 :: new ( ) ;
14088
14189 for class in input. classes {
142- let visibility = & class. visibility ;
143- let apply_name = apply_function_for_class_name ( & class. name ) ;
144- let mut apply_body = TokenStream2 :: new ( ) ;
145-
146- for ( name, value) in & class. properties {
147- let make_mut_name = syn:: Ident :: new ( & format ! ( "make_{name}_mut" ) , name. span ( ) ) ;
148-
149- apply_body. extend ( quote ! {
150- * current. #make_mut_name( ) = #value;
151- } ) ;
152- }
90+ let visibility = class. visibility ;
91+ let declarations_name = declarations_name_for_class_name ( & class. name ) ;
92+ let source = class. source ;
15393
15494 result. extend ( quote ! {
155- #visibility fn #apply_name( current: & mut crate :: style:: ComputedStyle ) {
156- #apply_body
157- }
158- } )
95+ #[ allow( non_upper_case_globals) ]
96+ #visibility static #declarations_name: std:: sync:: LazyLock <
97+ & ' static [ crate :: csssyn:: algorithms:: Declaration <' static >]
98+ > =
99+ std:: sync:: LazyLock :: new( || {
100+ let buffer = Box :: leak( Box :: new( crate :: csssyn:: TokenBuffer :: from_source( #source) . unwrap( ) ) ) ;
101+ let declarations = crate :: csssyn:: algorithms:: parse_declaration_list( buffer. start( ) ) ;
102+ Box :: leak( declarations. collect:: <Vec <_>>( ) . into_boxed_slice( ) )
103+ } ) ;
104+ } ) ;
159105 }
160106
161107 result. into ( )
162108}
163109
164110struct ApplyStyleInput {
165- target : syn:: Expr ,
166- name : syn:: Ident ,
111+ lctx : syn:: Expr ,
112+ parent : syn:: Expr ,
113+ classes : Vec < syn:: Ident > ,
167114}
168115
169116impl ApplyStyleInput {
170117 fn parse ( buffer : ParseStream , ctx : & mut ParseContext ) -> Result < Self , AlreadyReported > {
171118 Ok ( Self {
172- target : {
173- let target = buffer. parse :: < syn:: Expr > ( ) . report_in ( ctx) ?;
119+ lctx : {
120+ let lctx = buffer. parse :: < syn:: Expr > ( ) . report_in ( ctx) ?;
174121 buffer. parse :: < Token ! [ , ] > ( ) . report_in ( ctx) ?;
175- target
122+ lctx
123+ } ,
124+ parent : {
125+ let parent = buffer. parse :: < syn:: Expr > ( ) . report_in ( ctx) ?;
126+ buffer. parse :: < Token ! [ , ] > ( ) . report_in ( ctx) ?;
127+ parent
128+ } ,
129+ classes : {
130+ let mut result = Vec :: new ( ) ;
131+ while !buffer. is_empty ( ) {
132+ result. push ( buffer. parse :: < syn:: Ident > ( ) . report_in ( ctx) ?) ;
133+ }
134+ result
176135 } ,
177- name : buffer. parse :: < syn:: Ident > ( ) . report_in ( ctx) ?,
178136 } )
179137 }
180138}
181139
182- pub fn test_apply_style ( ts : proc_macro:: TokenStream ) -> proc_macro:: TokenStream {
140+ pub fn test_apply_styles ( ts : proc_macro:: TokenStream ) -> proc_macro:: TokenStream {
183141 let input = {
184142 let mut parse_ctx = ParseContext :: new ( ) ;
185143 let Ok ( input) = parse_ctx. parse2 ( ApplyStyleInput :: parse, ts. into ( ) ) else {
@@ -188,8 +146,18 @@ pub fn test_apply_style(ts: proc_macro::TokenStream) -> proc_macro::TokenStream
188146 input
189147 } ;
190148
191- let apply_name = apply_function_for_class_name ( & input. name ) ;
192- let target = input. target ;
193-
194- quote ! { #apply_name( #target) } . into ( )
149+ let lctx = input. lctx ;
150+ let parent = input. parent ;
151+ let class_declarations = input
152+ . classes
153+ . into_iter ( )
154+ . map ( |class| declarations_name_for_class_name ( & class) ) ;
155+
156+ quote ! { {
157+ let mut declarations = [
158+ #( #class_declarations. iter( ) , ) *
159+ ] . into_iter( ) . flatten( ) . cloned( ) . collect( ) ;
160+ crate :: style:: compute_with_declarations( #lctx, declarations, #parent)
161+ } }
162+ . into ( )
195163}
0 commit comments