@@ -2,7 +2,7 @@ use std::cell::Cell;
22use std:: os:: raw:: c_void;
33use std:: panic:: { catch_unwind, AssertUnwindSafe } ;
44use std:: ptr:: NonNull ;
5- use std:: time:: Duration ;
5+ use std:: time:: { Duration , Instant } ;
66use std:: { fmt, mem, ptr} ;
77
88use regex_cursor:: Cursor ;
@@ -32,6 +32,7 @@ impl Drop for RawParser {
3232/// source code.
3333pub struct Parser {
3434 ptr : NonNull < ParserData > ,
35+ timeout : Option < Duration > ,
3536}
3637
3738impl Parser {
@@ -46,7 +47,7 @@ impl Parser {
4647 }
4748 None => unsafe { ts_parser_new ( ) } ,
4849 } ;
49- Parser { ptr }
50+ Parser { ptr, timeout : None }
5051 }
5152
5253 /// Set the language that the parser should use for parsing.
@@ -55,11 +56,7 @@ impl Parser {
5556 }
5657
5758 pub fn set_timeout ( & mut self , duration : Duration ) {
58- // TODO: migrate away from timing and towards the progress API.
59- #[ allow( deprecated) ]
60- unsafe {
61- ts_parser_set_timeout_micros ( self . ptr , duration. as_micros ( ) . try_into ( ) . unwrap ( ) )
62- }
59+ self . timeout = Some ( duration) ;
6360 }
6461
6562 /// Set the ranges of text that the parser should include when parsing. By default, the parser
@@ -121,9 +118,25 @@ impl Parser {
121118 encoding : InputEncoding :: Utf8 ,
122119 decode : None ,
123120 } ;
121+
122+ let options = if let Some ( timeout) = self . timeout {
123+ unsafe extern "C" fn check_timeout ( state : NonNull < ParseState > ) -> bool {
124+ let & ( start, timeout) = state. as_ref ( ) . payload . cast ( ) . as_ref ( ) ;
125+ Instant :: now ( ) . duration_since ( start) > timeout
126+ }
127+
128+ let start = Instant :: now ( ) ;
129+ ParseOptions {
130+ payload : Some ( NonNull :: from ( & mut ( start, timeout) ) . cast ( ) ) ,
131+ progress_callback : Some ( check_timeout) ,
132+ }
133+ } else {
134+ ParseOptions :: default ( )
135+ } ;
136+
124137 unsafe {
125138 let old_tree = old_tree. map ( |tree| tree. as_raw ( ) ) ;
126- let new_tree = ts_parser_parse ( self . ptr , old_tree, input) ;
139+ let new_tree = ts_parser_parse_with_options ( self . ptr , old_tree, input, options ) ;
127140 new_tree. map ( |raw| SyntaxTree :: from_raw ( raw) )
128141 }
129142 }
@@ -190,6 +203,26 @@ pub enum InputEncoding {
190203 Custom ,
191204}
192205
206+ #[ repr( C ) ]
207+ #[ derive( Debug ) ]
208+ pub struct ParseState {
209+ /// The payload passed via `ParseOptions`' `payload` field.
210+ pub payload : NonNull < c_void > ,
211+ pub current_byte_offset : u32 ,
212+ pub has_error : bool ,
213+ }
214+
215+ /// A function that accepts the current parser state and returns `true` when the parse should be
216+ /// cancelled.
217+ type ProgressCallback = unsafe extern "C" fn ( state : NonNull < ParseState > ) -> bool ;
218+
219+ #[ repr( C ) ]
220+ #[ derive( Debug , Default ) ]
221+ pub struct ParseOptions {
222+ pub payload : Option < NonNull < c_void > > ,
223+ pub progress_callback : Option < ProgressCallback > ,
224+ }
225+
193226extern "C" {
194227 /// Create a new parser
195228 fn ts_parser_new ( ) -> NonNull < ParserData > ;
@@ -220,41 +253,31 @@ extern "C" {
220253 count : u32 ,
221254 ) -> bool ;
222255
223- /// Use the parser to parse some source code and create a syntax tree. If you are parsing this
224- /// document for the first time, pass `NULL` for the `old_tree` parameter. Otherwise, if you
225- /// have already parsed an earlier version of this document and the document has since been
226- /// edited, pass the previous syntax tree so that the unchanged parts of it can be reused.
227- /// This will save time and memory. For this to work correctly, you must have already edited
228- /// the old syntax tree using the [`ts_tree_edit`] function in a way that exactly matches
229- /// the source code changes. The [`TSInput`] parameter lets you specify how to read the text.
230- /// It has the following three fields: 1. [`read`]: A function to retrieve a chunk of text
231- /// at a given byte offset and (row, column) position. The function should return a pointer
232- /// to the text and write its length to the [`bytes_read`] pointer. The parser does not
233- /// take ownership of this buffer; it just borrows it until it has finished reading it. The
234- /// function should write a zero value to the [`bytes_read`] pointer to indicate the end of the
235- /// document. 2. [`payload`]: An arbitrary pointer that will be passed to each invocation of
236- /// the [`read`] function. 3. [`encoding`]: An indication of how the text is encoded. Either
237- /// `TSInputEncodingUTF8` or `TSInputEncodingUTF16`. This function returns a syntax tree
238- /// on success, and `NULL` on failure. There are three possible reasons for failure: 1. The
239- /// parser does not have a language assigned. Check for this using the [`ts_parser_language`]
240- /// function. 2. Parsing was cancelled due to a timeout that was set by an earlier call to the
241- /// [`ts_parser_set_timeout_micros`] function. You can resume parsing from where the parser
242- /// left out by calling [`ts_parser_parse`] again with the same arguments. Or you can start
243- /// parsing from scratch by first calling [`ts_parser_reset`]. 3. Parsing was cancelled using
244- /// a cancellation flag that was set by an earlier call to [`ts_parser_set_cancellation_flag`].
245- /// You can resume parsing from where the parser left out by calling [`ts_parser_parse`] again
246- /// with the same arguments. [`read`]: TSInput::read [`payload`]: TSInput::payload [`encoding`]:
247- /// TSInput::encoding [`bytes_read`]: TSInput::read
256+ /*
248257 fn ts_parser_parse(
249258 parser: NonNull<ParserData>,
250259 old_tree: Option<NonNull<SyntaxTreeData>>,
251260 input: ParserInputRaw,
252261 ) -> Option<NonNull<SyntaxTreeData>>;
262+
253263 /// Set the maximum duration in microseconds that parsing should be allowed to
254264 /// take before halting.
255265 ///
256266 /// If parsing takes longer than this, it will halt early, returning NULL.
257267 /// See [`ts_parser_parse`] for more information.
258268 #[deprecated = "use ts_parser_parse_with_options and pass in a calback instead, this will be removed in 0.26"]
259269 fn ts_parser_set_timeout_micros(self_: NonNull<ParserData>, timeout_micros: u64);
270+ */
271+
272+ /// User the parser to parse some source code and create a syntax tree, with some options.
273+ ///
274+ /// See `ts_parser_parse` for more details.
275+ ///
276+ /// See `TSParseOptions` for more details on the options.
277+ fn ts_parser_parse_with_options (
278+ parser : NonNull < ParserData > ,
279+ old_tree : Option < NonNull < SyntaxTreeData > > ,
280+ input : ParserInputRaw ,
281+ parse_options : ParseOptions ,
282+ ) -> Option < NonNull < SyntaxTreeData > > ;
260283}
0 commit comments