@@ -14,6 +14,12 @@ pub struct InstantiatedLanguage<'a> {
1414 run_query : QueryFunction ,
1515}
1616
17+ #[ derive( Debug ) ]
18+ pub enum InstantiationError {
19+ NoMatchingField ( String ) ,
20+ Query ( QueryError ) ,
21+ Tags ( tree_sitter_tags:: Error ) ,
22+ }
1723pub trait HasLanguageInformation {
1824 /// The name of this language
1925 fn language_name ( & self ) -> & ' static str ;
@@ -88,49 +94,59 @@ pub struct TreeSitter;
8894pub struct Tags ;
8995// TODO: hide in docs?
9096trait InstantiateHelper < Type > {
91- fn instantiate ( & self , search : Box < str > ) -> QueryFunction ;
97+ fn instantiate ( & self , search : Box < str > ) -> Result < QueryFunction , InstantiationError > ;
9298}
9399
94100// TODO: hide in docs?
95101pub trait Assoc {
96102 type Type ;
97103}
98104impl < T : IdentifierQuery > InstantiateHelper < Identifier > for T {
99- fn instantiate ( & self , search : Box < str > ) -> QueryFunction {
100- let query = Query :: new ( & self . language ( ) , & self . query_string ( ) . to_string ( ) ) . unwrap ( ) ;
101- let method_field = query
102- . capture_index_for_name ( & self . query_name ( ) . to_string ( ) )
103- . unwrap ( ) ;
104- Box :: new ( move |node, code| {
105- let name = & * search;
106- let mut query_cursor = tree_sitter:: QueryCursor :: new ( ) ;
107- let matches = query_cursor. matches ( & query, node, code) ;
108- let ranges = matches
109- . filter ( move |m| {
110- m. captures
111- . iter ( )
112- . any ( |c| c. index == method_field && c. node . utf8_text ( code) . unwrap ( ) == name)
113- } )
114- . map ( |m| m. captures [ 0 ] . node . range ( ) ) ;
115-
116- ranges. collect ( )
117- } )
105+ fn instantiate ( & self , search : Box < str > ) -> Result < QueryFunction , InstantiationError > {
106+ Query :: new ( & self . language ( ) , & self . query_string ( ) . to_string ( ) )
107+ . map_err ( InstantiationError :: Query )
108+ . and_then ( |query : Query | {
109+ query
110+ . capture_index_for_name ( & self . query_name ( ) . to_string ( ) )
111+ . ok_or_else ( || {
112+ InstantiationError :: NoMatchingField ( self . query_name ( ) . to_string ( ) )
113+ } )
114+ . map ( |method_field| -> QueryFunction {
115+ Box :: new ( move |node, code| {
116+ let name = & * search;
117+ let mut query_cursor = tree_sitter:: QueryCursor :: new ( ) ;
118+ let matches = query_cursor. matches ( & query, node, code) ;
119+ let ranges = matches
120+ . filter ( move |m| {
121+ m. captures . iter ( ) . any ( |c| {
122+ c. index == method_field
123+ && c. node . utf8_text ( code) . unwrap_or ( "" ) == name
124+ } )
125+ } )
126+ . map ( |m| m. captures [ 0 ] . node . range ( ) ) ;
127+
128+ ranges. collect ( )
129+ } )
130+ } )
131+ } )
118132 }
119133}
120134impl < T : TreeSitterQuery > InstantiateHelper < TreeSitter > for T {
121- fn instantiate ( & self , search : Box < str > ) -> QueryFunction {
122- let query = Query :: new (
135+ fn instantiate ( & self , search : Box < str > ) -> Result < QueryFunction , InstantiationError > {
136+ Query :: new (
123137 & self . language ( ) ,
124138 & self . query_string_function ( search. as_ref ( ) ) ,
125139 )
126- . unwrap ( ) ;
127- Box :: new ( move |node, code| {
128- let mut query_cursor = tree_sitter:: QueryCursor :: new ( ) ;
129- let matches = query_cursor. matches ( & query, node, code) ;
130-
131- let ranges = matches. map ( |m| m. captures [ 0 ] . node . range ( ) ) ;
132- ranges. collect ( )
140+ . map ( |query| -> QueryFunction {
141+ Box :: new ( move |node, code| {
142+ let mut query_cursor = tree_sitter:: QueryCursor :: new ( ) ;
143+ let matches = query_cursor. matches ( & query, node, code) ;
144+
145+ let ranges = matches. map ( |m| m. captures [ 0 ] . node . range ( ) ) ;
146+ ranges. collect ( )
147+ } )
133148 } )
149+ . map_err ( InstantiationError :: Query )
134150 }
135151}
136152struct TagsConfigurationThreadSafe ( TagsConfiguration ) ;
@@ -156,64 +172,75 @@ impl TagsConfigurationThreadSafe {
156172 }
157173}
158174impl < T : TreeSitterTags > InstantiateHelper < Tags > for T {
159- fn instantiate ( & self , search : Box < str > ) -> QueryFunction {
160- let tag_config = TagsConfigurationThreadSafe (
161- TagsConfiguration :: new ( self . language ( ) , & self . tag_query ( ) . to_string ( ) , "" ) . unwrap ( ) ,
162- ) ;
163- Box :: new ( move |node, code| {
164- let mut tag_context = TagsContext :: new ( ) ;
165- let name = & * search;
166- // TODO: don't double parse
167- let tags = tag_config
168- . generate_tags ( & mut tag_context, code, None )
169- . unwrap ( )
170- . 0 ;
171- let ranges = tags
172- . filter_map ( Result :: ok)
173- . filter ( |tag| {
174- [ "method" , "function" ]
175- . contains ( & tag_config. syntax_type_name ( tag. syntax_type_id ) )
176- && str:: from_utf8 ( & code[ tag. name_range . clone ( ) ] ) . unwrap_or ( "" ) == name
175+ fn instantiate ( & self , search : Box < str > ) -> Result < QueryFunction , InstantiationError > {
176+ TagsConfiguration :: new ( self . language ( ) , & self . tag_query ( ) . to_string ( ) , "" )
177+ . map_err ( InstantiationError :: Tags )
178+ . map ( |tag_config| -> QueryFunction {
179+ let tag_config = TagsConfigurationThreadSafe ( tag_config) ;
180+ Box :: new ( move |node, code| {
181+ let mut tag_context = TagsContext :: new ( ) ;
182+ let name = & * search;
183+ // TODO: don't double parse
184+ tag_config
185+ . generate_tags ( & mut tag_context, code, None )
186+ . map ( |tags| {
187+ let ranges = tags
188+ . 0
189+ . filter_map ( Result :: ok)
190+ . filter ( |tag| {
191+ [ "method" , "function" ]
192+ . contains ( & tag_config. syntax_type_name ( tag. syntax_type_id ) )
193+ && str:: from_utf8 ( & code[ tag. name_range . clone ( ) ] )
194+ . unwrap_or ( "" )
195+ == name
196+ } )
197+ . filter_map ( |tag| {
198+ node. descendant_for_byte_range ( tag. range . start , tag. range . end )
199+ . map ( |node| node. range ( ) )
200+ } ) ;
201+ ranges. collect ( )
202+ } )
203+ . unwrap_or_else ( |_| vec ! [ ] . into_boxed_slice ( ) )
177204 } )
178- . filter_map ( |tag| {
179- node. descendant_for_byte_range ( tag. range . start , tag. range . end )
180- . map ( |node| node. range ( ) )
181- } ) ;
182- ranges. collect ( )
183- } )
205+ } )
184206 }
185207}
208+
186209impl < T : Assoc + InstantiateHelper < T :: Type > + HasLanguageInformation > SupportedLanguage for T {
187- fn instantiate ( & self , search : Box < str > ) -> QueryFunction {
210+ fn instantiate ( & self , search : Box < str > ) -> Result < QueryFunction , InstantiationError > {
188211 self . instantiate ( search)
189212 }
190213}
214+ // TODO: maybe make this fallable
191215type QueryFunction = Box < dyn for <' x , ' y > Fn ( Node < ' x > , & ' y [ u8 ] ) -> Box < [ Range ] > + Send + Sync > ;
192216
193217pub trait SupportedLanguage : HasLanguageInformation {
194- fn instantiate ( & self , search : Box < str > ) -> QueryFunction ;
195- fn to_language < ' a > ( & self , search : & ' a str ) -> InstantiatedLanguage < ' a > {
196- InstantiatedLanguage :: new (
197- search ,
198- self . language_info ( ) ,
199- self . instantiate ( search. into ( ) ) ,
200- )
218+ fn instantiate ( & self , search : Box < str > ) -> Result < QueryFunction , InstantiationError > ;
219+ fn to_language < ' a > (
220+ & self ,
221+ search : & ' a str ,
222+ ) -> Result < InstantiatedLanguage < ' a > , InstantiationError > {
223+ self . instantiate ( search. into ( ) )
224+ . map ( |f| InstantiatedLanguage :: new ( search , self . language_info ( ) , f ) )
201225 }
202226}
203227
204228pub trait InstantiateMap < ' a > {
205- fn instantiate_map ( self , name : & ' a str ) -> Result < Vec < InstantiatedLanguage < ' a > > , QueryError > ;
229+ fn instantiate_map (
230+ self ,
231+ name : & ' a str ,
232+ ) -> Result < Vec < InstantiatedLanguage < ' a > > , InstantiationError > ;
206233}
207234impl < ' a , T , U > InstantiateMap < ' a > for T
208235where
209236 T : IntoIterator < Item = U > ,
210237 U : Deref < Target = & ' a dyn SupportedLanguage > ,
211238{
212- fn instantiate_map ( self , name : & ' a str ) -> Result < Vec < InstantiatedLanguage < ' a > > , QueryError > {
213- Ok ( self
214- . into_iter ( )
215- . map ( |l| InstantiatedLanguage :: new ( name , l . language_info ( ) , l . instantiate ( name . into ( ) ) ) )
216- . collect ( ) )
239+ fn instantiate_map (
240+ self ,
241+ name : & ' a str ,
242+ ) -> Result < Vec < InstantiatedLanguage < ' a > > , InstantiationError > {
243+ self . into_iter ( ) . map ( |l| l . to_language ( name ) ) . collect ( )
217244 }
218245}
219246impl < ' a > InstantiatedLanguage < ' a > {
0 commit comments