@@ -117,14 +117,10 @@ impl RawAttrs {
117117 None => return smallvec ! [ attr. clone( ) ] ,
118118 } ;
119119 let index = attr. id ;
120- let attrs =
121- parts. enumerate ( ) . take ( 1 << AttrId :: CFG_ATTR_BITS ) . filter_map ( |( idx, attr) | {
122- let tree = Subtree {
123- delimiter : tt:: Delimiter :: invisible_spanned ( attr. first ( ) ?. first_span ( ) ) ,
124- token_trees : attr. to_vec ( ) ,
125- } ;
126- Attr :: from_tt ( db, & tree, index. with_cfg_attr ( idx) )
127- } ) ;
120+ let attrs = parts
121+ . enumerate ( )
122+ . take ( 1 << AttrId :: CFG_ATTR_BITS )
123+ . filter_map ( |( idx, attr) | Attr :: from_tt ( db, attr, index. with_cfg_attr ( idx) ) ) ;
128124
129125 let cfg_options = & crate_graph[ krate] . cfg_options ;
130126 let cfg = Subtree { delimiter : subtree. delimiter , token_trees : cfg. to_vec ( ) } ;
@@ -222,12 +218,41 @@ impl Attr {
222218 Some ( Attr { id, path, input, span } )
223219 }
224220
225- fn from_tt ( db : & dyn ExpandDatabase , tt : & tt:: Subtree , id : AttrId ) -> Option < Attr > {
226- // FIXME: Unecessary roundtrip tt -> ast -> tt
227- let ( parse, map) = mbe:: token_tree_to_syntax_node ( tt, mbe:: TopEntryPoint :: MetaItem ) ;
228- let ast = ast:: Meta :: cast ( parse. syntax_node ( ) ) ?;
229-
230- Self :: from_src ( db, ast, SpanMapRef :: ExpansionSpanMap ( & map) , id)
221+ fn from_tt ( db : & dyn ExpandDatabase , tt : & [ tt:: TokenTree ] , id : AttrId ) -> Option < Attr > {
222+ dbg ! ( tt) ;
223+ let span = tt. first ( ) ?. first_span ( ) ;
224+ let path_end = tt
225+ . iter ( )
226+ . position ( |tt| {
227+ !matches ! (
228+ tt,
229+ tt:: TokenTree :: Leaf (
230+ tt:: Leaf :: Punct ( tt:: Punct { char : ':' | '$' , .. } ) | tt:: Leaf :: Ident ( _) ,
231+ )
232+ )
233+ } )
234+ . unwrap_or_else ( || tt. len ( ) ) ;
235+
236+ let ( path, input) = tt. split_at ( path_end) ;
237+ let path = Interned :: new ( ModPath :: from_tt ( db, path) ?) ;
238+
239+ let input = match input. get ( 0 ) {
240+ Some ( tt:: TokenTree :: Subtree ( tree) ) => {
241+ Some ( Interned :: new ( AttrInput :: TokenTree ( Box :: new ( tree. clone ( ) ) ) ) )
242+ }
243+ Some ( tt:: TokenTree :: Leaf ( tt:: Leaf :: Punct ( tt:: Punct { char : '=' , .. } ) ) ) => {
244+ let input = match input. get ( 1 ) {
245+ Some ( tt:: TokenTree :: Leaf ( tt:: Leaf :: Literal ( tt:: Literal { text, .. } ) ) ) => {
246+ //FIXME the trimming here isn't quite right, raw strings are not handled
247+ Some ( Interned :: new ( AttrInput :: Literal ( text. trim_matches ( '"' ) . into ( ) ) ) )
248+ }
249+ _ => None ,
250+ } ;
251+ input
252+ }
253+ _ => None ,
254+ } ;
255+ Some ( Attr { id, path, input, span } )
231256 }
232257
233258 pub fn path ( & self ) -> & ModPath {
@@ -277,29 +302,8 @@ impl Attr {
277302 . token_trees
278303 . split ( |tt| matches ! ( tt, tt:: TokenTree :: Leaf ( tt:: Leaf :: Punct ( Punct { char : ',' , .. } ) ) ) )
279304 . filter_map ( move |tts| {
280- if tts. is_empty ( ) {
281- return None ;
282- }
283- // FIXME: This is necessarily a hack. It'd be nice if we could avoid allocation
284- // here or maybe just parse a mod path from a token tree directly
285- let subtree = tt:: Subtree {
286- delimiter : tt:: Delimiter :: invisible_spanned ( tts. first ( ) ?. first_span ( ) ) ,
287- token_trees : tts. to_vec ( ) ,
288- } ;
289- let ( parse, span_map) =
290- mbe:: token_tree_to_syntax_node ( & subtree, mbe:: TopEntryPoint :: MetaItem ) ;
291- let meta = ast:: Meta :: cast ( parse. syntax_node ( ) ) ?;
292- // Only simple paths are allowed.
293- if meta. eq_token ( ) . is_some ( ) || meta. expr ( ) . is_some ( ) || meta. token_tree ( ) . is_some ( )
294- {
295- return None ;
296- }
297- let path = meta. path ( ) ?;
298- let call_site = span_map. span_at ( path. syntax ( ) . text_range ( ) . start ( ) ) ;
299- Some ( (
300- ModPath :: from_src ( db, path, SpanMapRef :: ExpansionSpanMap ( & span_map) ) ?,
301- call_site,
302- ) )
305+ let span = tts. first ( ) ?. first_span ( ) ;
306+ Some ( ( ModPath :: from_tt ( db, tts) ?, span) )
303307 } ) ;
304308
305309 Some ( paths)
0 commit comments